GeekBits

Read a File in C

In this one, we will cover all the methods and techniques that you can use to read a file in the C programming language, including all the safe and unsafe methods. We belive the best defense is offense. Learn about the ones not to use so you learn how to handle them or exploit them if necessary 😄

3 min read
Read a File in C

File operations and handling is one of the most fundamental programming tasks for everyone. Whether a newbie or a seasoned pro, you are going to create, read, write, and delete a file in your application.

This is no difference when it comes to the C programming language. One difference between C and other language is that they do not hold your hand.

You have control over which technique you use to use but with a very potentiality of unsafe implementations if used incorrectly.

The Basics

In C, we use deal with file operations by using the stdio.h header files. This header file contains the necessary functions for I/O operations.

To read a file, it will typically involve the following four basic steps.

  1. Include the necessary header files.
  2. Open the file using fopen() to create a file pointer.
  3. Read data from the file using various methods.
  4. Close the file using fclose() when done.

This should outline the foundation of how each method can read a file.

Method 1 - Using fgetc (Unsafe).

The first method we will discuss is the fgetfunction. This function allows us to read a single character from a file and return it as an int.

One disadavantage of this method is that it can be unsafe as it does not handle end-of-file conditons gracefully.

Let us look at an example.

#include <stdio.h>

int main() {
    FILE *file = fopen("hello.txt", "r"); // Open in read

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    int character;

    while ((character = fgetc(file)) != EOF) {
        putchar(character); // Print character to the console
    }

    fclose(file); // close file
    return 0;
}

In this case, we use the fgetc function to read a single character from the specifed file. An example output is as shown:

hello from c% 

One advantage of this method is very straightforward and intuitive.

Method 2 - Using fgets() (Safe)

The second and alternative to the fgetc() function is the fgets() function. Unlike fgetc, this function reads a line of text from a file and stores the resulting data as a string.

This function is much safer than fgetc as it able to handles buffer overflows much better and does allow us to read lines at a time.

An example is as shown below:

#include <stdio.h>

int main() {
    FILE *file = fopen("hello.txt", "r");

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    char line[100]; // Buffer to store the line

    while (fgets(line, sizeof(line), file) != NULL) {
        printf("%s", line); // Print the line to the console
    }

    fclose(file);
    return 0;
}

Output is as shown:

hello from c% 

The main drawback of this method is that you may need to implement extra processing for non-line based data.

Method 3 - Using fread() (Unsafe)

Third in the line is the bread() function. This function allows us to read binary data from a file which makes it very powerful.

However, it can be unsafe when dealign with text file due to the lack of specific implementations to handle text files such as character encoding.

An example is as shown below:

#include <stdio.h>

int main() {
    FILE *file = fopen("fsociety00.dat", "rb");

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    char buffer[100];

    while (fread(buffer, sizeof(char), sizeof(buffer), file) > 0) {
        // Process binary data in 'buffer'
    }

    fclose(file);
    return 0;
}

In this example, we demonstrate how to use the fread function to read a binary file in the specified path.

Similarly, the method might not work well with variable-length records.

Method 4 - Using fscanf() (Safe)

The fscanf() function allows us to read formatted data from a text file. This function is safe and quite efficient for reading structured data.

An example is as shown:

#include <stdio.h>

int main() {
    FILE *file = fopen("hello.txt", "r");

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    int intValue;
    float floatValue;
    char string[100];

    while (fscanf(file, "%d %f %s", &intValue, &floatValue, string) != EOF) {
        printf("Int: %d, Float: %f, String: %s\n", intValue, floatValue, string);
    }

    fclose(file);
    return 0;
}

This should read the file in the specified path and return the contents. This method is quite good and safe at reading text files and other data types.

Method 5 - Using fgets() and sscanf() (Safe)

Lastly, we have a method that combines fgets() to read lines and sscanf() to parse formatted data. It offers flexibility and safety for reading structured text data.

An example is as shown:

#include <stdio.h>

int main() {
    FILE *file = fopen("hello.txt", "r");

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    char line[100];

    while (fgets(line, sizeof(line), file) != NULL) {
        int intValue;
        float floatValue;
        char string[100];

        if (sscanf(line, "%d %f %s", &intValue, &floatValue, string) == 3) {
            printf("Int: %d, Float: %f, String: %s\n", intValue, floatValue, string);
        }
    }

    fclose(file);
    return 0;
}

This technique is safe and flexible to even handle text data. It does however require extra processing to split lines and parse data.

Conclusion

In this guide, we learned all the various methods that we can use to read a file in the C programming language, including the safe and unsafe methods and potential pitfalls.

Sign up for our newsletter

Don't miss anything. Get all the latest posts delivered to your inbox. No spam!