File I/O (Input/Output) in C allows programs to store and retrieve data from files, making it essential for creating applications that manage persistent data. Common file operations include reading data from files, writing data to files, and appending content. In this article, we will go over practical examples that demonstrate how to perform these operations in C.
To work with a file, it must first be opened using the fopen
function, which returns a file pointer. The fopen
function takes two arguments: the filename and the mode of operation (such as r
for reading or w
for writing).
#include <stdio.h> int main() { FILE *file = fopen("data.txt", "r"); if (file == NULL) { printf("Error opening file.\n"); return 1; } // Perform file operations fclose(file); return 0; }
Writing to a file is achieved with the fprintf
or fputs
functions. These functions allow you to write formatted data to the file.
#include <stdio.h> int main() { FILE *file = fopen("output.txt", "w"); if (file == NULL) { printf("Error opening file for writing.\n"); return 1; } fprintf(file, "Hello, world!\n"); fprintf(file, "Writing to files in C is simple!\n"); fclose(file); return 0; }
This example creates output.txt
(or overwrites it if it exists) and writes two lines to it using fprintf
.
To read data from a file, you can use the fscanf
or fgets
functions. fscanf
is useful for formatted data, while fgets
is used to read strings line by line.
#include <stdio.h> int main() { FILE *file = fopen("output.txt", "r"); if (file == NULL) { printf("Error opening file for reading.\n"); return 1; } char line[100]; while (fgets(line, sizeof(line), file) != NULL) { printf("%s", line); } fclose(file); return 0; }
This example reads each line from output.txt
and prints it to the console. It uses fgets
to read the file line by line.
Appending allows you to add data to the end of an existing file without overwriting its contents. This can be done using the a
mode in fopen
.
#include <stdio.h> int main() { FILE *file = fopen("output.txt", "a"); if (file == NULL) { printf("Error opening file for appending.\n"); return 1; } fprintf(file, "Appending a new line.\n"); fclose(file); return 0; }
Here, output.txt
is opened in append mode, and a new line is added without affecting existing content.
C can also write and read numeric data using fprintf
and fscanf
.
#include <stdio.h> int main() { FILE *file = fopen("numbers.txt", "w"); if (file == NULL) { printf("Error opening file for writing.\n"); return 1; } int number = 25; fprintf(file, "%d\n", number); // Write a number fclose(file); // Reopen for reading file = fopen("numbers.txt", "r"); if (file == NULL) { printf("Error opening file for reading.\n"); return 1; } fscanf(file, "%d", &number); // Read the number printf("Read number: %d\n", number); fclose(file); return 0; }
This example writes an integer to a file and then reads it back.
Binary file I/O is useful when dealing with non-text data such as images or custom data structures. Binary files can be written with fwrite
and read with fread
.
#include <stdio.h> int main() { FILE *file = fopen("data.bin", "wb"); if (file == NULL) { printf("Error opening file for binary writing.\n"); return 1; } int numbers[] = {1, 2, 3, 4, 5}; fwrite(numbers, sizeof(int), 5, file); // Write array to binary file fclose(file); // Reopen for reading file = fopen("data.bin", "rb"); if (file == NULL) { printf("Error opening file for binary reading.\n"); return 1; } int read_numbers[5]; fread(read_numbers, sizeof(int), 5, file); // Read array from binary file fclose(file); for (int i = 0; i < 5; i++) { printf("Number %d: %d\n", i + 1, read_numbers[i]); } return 0; }
This example writes an integer array to a binary file and then reads it back into another array.
The feof
function checks if the end of a file has been reached during reading. This can be useful for handling the end-of-file condition gracefully.
#include <stdio.h> int main() { FILE *file = fopen("output.txt", "r"); if (file == NULL) { printf("Error opening file.\n"); return 1; } char ch; while ((ch = fgetc(file)) != EOF) { putchar(ch); } if (feof(file)) { printf("\nEnd of file reached.\n"); } fclose(file); return 0; }
In this example, feof
confirms when the end of output.txt
is reached.
Always check if a file operation succeeds, especially when opening files, to avoid runtime errors. For instance, if fopen
returns NULL
, it indicates a failure to open the file, possibly due to missing permissions or a non-existent file.
#include <stdio.h> #include <errno.h> int main() { FILE *file = fopen("nonexistent.txt", "r"); if (file == NULL) { perror("Error opening file"); return 1; } // File operations fclose(file); return 0; }
In this example, perror
outputs a description if fopen
fails.
File I/O in C is versatile, providing capabilities for reading, writing, appending, and handling binary data. Practical file handling techniques, error checking, and using the appropriate modes for operations make it possible to create efficient, data-driven programs. Understanding these basic file I/O concepts is essential for building more complex C applications