File Handling


File handling in C is a fundamental aspect of programming that allows us to interact with files on a computer’s storage system. In the C programming language, file handling is achieved through standard library functions defined in <stdio.h> The following operations can be performed on a file:-

  • Creating a new file
  • Opening an existing file
  • Reading data from an existing file
  • Writing data to a file
  • Moving data to a specific location on the file
  • Closing the file

Why Do We Need File Handling in C?

There are times when, despite compiling and running a program, the output generated does not serve our intended purpose. In such cases, we might want to check the program’s output various times. Now, compiling and running the very same program multiple times becomes a tedious task for any programmer. It is exactly where file handling becomes useful. Let us look at a few reasons why file handling makes programming easier for all:

  • Reusability: File handling allows us to preserve the information/data generated after we run the program.

  • Saves Time: Some programs might require a large amount of input from their users. In such cases, file handling allows you to easily access a part of a code using individual commands.

  • Commendable storage capacity: When storing data in files, however, you can leave behind the worry of storing all the info in bulk in any program.

  • Portability:  We can transfer the contents available in any file to another one in the computer system without any data loss. This saves a lot of effort and minimises the risk of flawed coding.

Types of Files in a C Program

When referring to file handling, we refer to files in the form of data files. Now, these data files are available in 2 distinct forms in the C language, namely:

  • Text Files
  • Binary Files
  • Random Access file

Text Files

A text file contains data in the form of ASCII characters and is generally used to store a stream of characters.

  • Each line in a text file ends with a new line character (‘\n’).
  • Any text editor can read or write it.
  • Generally, they store these files with a .txt file extension.
  • Text files can also store the source code.

Binary Files

A binary file contains data in binary form (i.e. 0’s and 1’s) instead of ASCII characters. They contain data that is stored in a similar manner to how it is stored in the main memory.

  • The binary files can be created only from within a program and their contents can only be read by a program.
  • More secure as they are not easily readable.
  • They are generally stored with .bin file extension.

Random Access file

Random file access means that you can take the file pointer to any part of the file for reading or writing. There is no need to read each record sequentially, if we want to access a particular record. C supports these functions for random access file processing:- fseek(), ftell(), rewind().


Functions For File Handling

We can use a variety of functions in order to open a file, read it, write more data, create a new file, close or delete a file, search for a file, etc. These are known as file handling operators in C. Here’s a list of functions that allow you to do so:

FunctionDescription
    fopen()Creates a new file and Opens and existing file for use.
    fclose()Closes a file which has been opened for use.
    fgetc()Reads a character from a file.
    fputc()Writes a character to a file.
    fprintf()Writes a set of data values to a file.
    fscanf()Reads a set of data values from a file.
    fgetw()Reads an integer from a file.
    fputw()Writes an integer to a file.
    fseek()Sets the position to a desired point in the file.
    ftell()Gives the current position in the file.
    rewind()Sets the position to the beginning of the file..


Note
: Firstly, it is important to know that we must declare a file-type pointer when we are working with various files in a program. This helps establish direct communication between a program and the files. Here is how you can do it: FILE *fpointer; Out of all the operations/functions mentioned above, let us discuss some of the basic operations that we perform in the C language.


Here’s an overview of the basic file handling functions in C:

  • fopen(): The fopen() function is used to open a file. It takes two arguments: the file path and the mode. The mode specifies whether the file will open for reading, writing, or both. The function returns a pointer to a FILE structure that represents the opened file.
FILE* fopen(const char* filename, const char* mode);
  • fclose(): The fclose() function is used to close a file that was previously opened with fopen(). It takes a pointer to a FILE structure as an argument.
int fclose(FILE* stream);
  • fputc(), fgetc(), fputs(), and fgets(): These functions are used for reading and writing individual characters or strings to and from files.
int fputc(int character, FILE* stream);
int fgetc(FILE* stream);
int fputs(const char* str, FILE* stream);
char* fgets(char* str, int num, FILE* stream);
  • fwrite() and fread(): These functions are used for reading and writing blocks of data to and from files.
size_t fwrite(const void* ptr, size_t size, 
size_t count, FILE* stream);

size_t fread(void* ptr, size_t size, size_t count, FILE* stream);
  • feof(): The feof() function checks if the end of the file has been reached.
int feof(FILE* stream);
  • fseek() and ftell(): These functions are used for file positioning.
int fseek(FILE* stream, long offset, int origin);
long ftell(FILE* stream);

Let us take a look at a few more opening modes used in the C programs:

Opening Modes of C in Standard I/O of a Program
Mode in ProgramMeaning of ModeWhen the file doesn’t exist
r
Open a file for reading the content.In case the file doesn’t exist in the location, then fopen() will return NULL.
rb
Open a file for reading the content in binary mode.In case the file doesn’t exist in the location, then fopen() will return NULL.
w
Open a file for writing the content.In case the file exists, its contents are overwritten.   In case the file doesn’t exist in the location, then it will create a new file.
wb
Open a file for writing the content in binary mode.In case the file exists, then its contents will get overwritten.   In case the file doesn’t exist in the location, then it will create a new file.
a
Open a file for appending the content.In case the file doesn’t exist in the location, then it will create a new file.
ab
Open a file for appending the content in binary mode.In case the file doesn’t exist in the location, then it will create a new file.
r+
Open a file for both writing and reading the content.In case the file doesn’t exist in the location, then fopen() will return NULL.
rb+
Open a file for both writing and reading the content in binary mode.In case the file doesn’t exist in the location, then fopen() will return NULL.
w+
Open a file for both writing and reading.In case the file exists, its contents are overwritten.   In case the file doesn’t exist in the location, then it will create a new file.
wb+
Open a file for both writing and reading the content in binary mode.In case the file exists, its contents are overwritten.   In case the file doesn’t exist in the location, then it will create a new file.
a+
Open a file for both appending and reading the content.In case the file doesn’t exist in the location, then it will create a new file.
ab+
Open a file for both appending and reading the content in binary mode.In case the file doesn’t exist in the location, then it will create a new file.

As given above, if you want to perform operations on a binary file, then you have to append ‘b’ at the last. For example, instead of “w”, you have to use “wb”, instead of “a+” you have to use “a+b”. Always handle errors properly when working with files, and remember to close the file using fclose() after we finish with it to release system resources.


Here’s a simple example of reading and writing to a file in C:

#include <stdio.h>

int main() {
    FILE* file = fopen("example.txt", "w");
    if (file != NULL) {
        fputs("Hello, File Handling in C!", file);
        fclose(file);
    } else {
        printf("Failed to open the file.\n");
        return 1;
    }

    file = fopen("example.txt", "r");
    if (file != NULL) {
        char buffer[100];
        fgets(buffer, sizeof(buffer), file);
        printf("Content read from file: %s\n", buffer);
        fclose(file);
    } else {
        printf("Failed to open the file.\n");
        return 1;
    }

    return 0;
}


Random Access To Files

ftell()

ftell() takes a file pointer and returns a number of type long, that corresponds to the current position. This function is useful in saving the current position of a file.

n=ftell(fp)

n would give the relative offset( in bytes ) of the current position. This means that the program has already read or written n bytes.  

rewind()

rewind takes a file pointer and resets the position to the start of the file.

rewind(fp);
n = ftell(fp);

After using the `rewind` function, remember that it sets the file position to the start of the file. Keep in mind that you should number the first byte in the file as 0, the second as 1, and so on.  

fseek()

The fseek function allows programmers to move the file position to a desired location within the file.

fseek(file ptr, offset, position);


For instance:

#include <stdio.h>

int main() {
    FILE* filePointer = fopen("data.txt", "r");
    if (filePointer == NULL) {
        printf("Error opening the file.\n");
        return 1;
    }

    fseek(filePointer, 10, SEEK_SET); 
 // Move the file pointer to the 10th byte from the beginning.

    char buffer[100];
    while (fgets(buffer, sizeof(buffer), filePointer) != NULL) {
        printf("%s", buffer);
    }

    fclose(filePointer);
    return 0;
}

The position can take one of the following those values:  

ValueMeaning
0Beginning of file
1Current position
2End of file

The offset may be positive, meaning move forward, or negative, meaning move backwards.

For Example:

StatementsMeaning
fseek(fp,0L,0);Beginning of file
fseek(fp,0L,1);Current position
fseek(fp,0L,2);End of file
fseek(fp,m,0);Move to (m+1)th byte in the file.
fseek(fp,m,1);Go forward by m bytes.
fseek(fp,-m,1);Go forward by m bytes from the current position
fseek(fp,-m,2);Go backwards by m bytes from the end.

Error Handling

Error Handling During I/O Operations

It is possible that an error occur during I/O operations on a file. Typical error situations includes:

  • Trying to read beyond the end-of-file mark.
  • Device overflow.
  • Trying to use an unopened file.
  • When storing data in files, you can confidently leave behind the worry of storing all the information in bulk within any program. Additionally, using this approach, you can better manage, access, and organize the data efficiently.
  • Opening a file with an invalid filename.
  • Lastly, attempting to write to a write-protected file.

Error Handling in File Operations

When dealing with file handling in C, however, it is crucial to handle errors properly to ensure robustness and prevent unexpected behavior. To check for errors during file operations, you can use the errno variable and the perror() function:

#include <stdio.h>

int main() {
    FILE* filePointer = fopen("data.txt", "r");
    if (filePointer == NULL) {
        perror("Error");
        return 1;
    }

    // File operations here...

    fclose(filePointer);
    return 0;
}

Furthermore, the perror() function will print an error message describing the error that occurred during the file operation.

Divide by Zero Errors

It is a common problem that at the time of dividing any number, programmers often do not check if a divisor is zero, and finally, it creates a runtime error.  

Program Exit Status

In this, it provides an exit() function which takes two values for printing successful or unsuccessful termination by using EXIT_SUCCESS and EXIT_FAILURE. Lastly, the standard library header file “stdlib.h” defines the exit() function.