Practical Examples of File I/O
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.
Opening a File
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 Data to a File
Writing to a file is achieved with the fprintf or fputs functions. These functions allow you to write formatted data to the file.
Example: Writing Text to a 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.
Reading Data from a File
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.
Example: Reading Text from a File
#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 Data to a File
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.
Example: Appending Data to a File
#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.
Working with Numbers
C can also write and read numeric data using fprintf and fscanf.
Example: Writing and Reading Numbers
#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
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.
Example: Writing and Reading Binary Data
#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.
Checking for End of File
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.
Example: Using feof
#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.
Error Handling
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.
Example: Checking fopen and perror
#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.
Conclusion
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