C File Handling Explained: Read, Write, Append, and Manage Files
File handling allows C programs to store and retrieve data from files. Instead of keeping information only in memory while a program is running, files make it possible to preserve data between program executions.
What is File Handling in C?
C provides file-handling functions through the stdio.h header. A FILE pointer represents an open stream and is used with functions for reading, writing, and managing files.
#include <stdio.h>
int main(void)
{
FILE *file;
file = fopen("data.txt", "r");
if (file == NULL)
{
printf("Could not open file.\n");
return 1;
}
fclose(file);
return 0;
}
Opening a File with fopen
The fopen function opens a file and returns a FILE pointer. If the operation fails, it returns NULL.
FILE *file = fopen("data.txt", "r");
if (file == NULL)
{
printf("Failed to open file.\n");
return 1;
}
File Opening Modes
| Mode | Purpose |
|---|---|
| r | Open an existing file for reading |
| w | Open for writing and create or truncate the file |
| a | Open for writing at the end of the file |
| r+ | Open an existing file for reading and writing |
| w+ | Open for reading and writing, creating or truncating the file |
| a+ | Open for reading and writing with writes at the end |
Writing Text with fprintf
fprintf writes formatted text to a file in a way similar to printf writing to standard output.
#include <stdio.h>
int main(void)
{
FILE *file = fopen("data.txt", "w");
if (file == NULL)
{
return 1;
}
fprintf(file, "Name: %s\n", "Alex");
fprintf(file, "Age: %d\n", 25);
fprintf(file, "Score: %.2f\n", 91.5);
fclose(file);
return 0;
}
Writing Text with fputs
fputs writes a string to a file stream.
#include <stdio.h>
int main(void)
{
FILE *file = fopen("message.txt", "w");
if (file == NULL)
{
return 1;
}
fputs("Hello from C!\n", file);
fputs("File handling is useful.\n", file);
fclose(file);
return 0;
}
Writing a Character with fputc
fputc writes a single character to a file stream.
#include <stdio.h>
int main(void)
{
FILE *file = fopen("letters.txt", "w");
if (file == NULL)
{
return 1;
}
fputc('A', file);
fputc('B', file);
fputc('C', file);
fclose(file);
return 0;
}
Reading Text with fgets
fgets reads a line or a portion of a line from a file into a character array.
#include <stdio.h>
int main(void)
{
FILE *file = fopen("data.txt", "r");
if (file == NULL)
{
return 1;
}
char line[256];
while (fgets(line, sizeof line, file) != NULL)
{
printf("%s", line);
}
fclose(file);
return 0;
}
Reading Characters with fgetc
fgetc reads one character at a time and returns EOF when the end of the input stream is reached or an input error occurs.
#include <stdio.h>
int main(void)
{
FILE *file = fopen("data.txt", "r");
if (file == NULL)
{
return 1;
}
int ch;
while ((ch = fgetc(file)) != EOF)
{
putchar(ch);
}
fclose(file);
return 0;
}
Formatted Input with fscanf
fscanf can read formatted data from a file stream. It is useful when the file contains predictable structured input.
#include <stdio.h>
int main(void)
{
FILE *file = fopen("numbers.txt", "r");
if (file == NULL)
{
return 1;
}
int a;
int b;
if (fscanf(file, "%d %d", &a, &b) == 2)
{
printf("Sum: %d\n", a + b);
}
fclose(file);
return 0;
}
Appending Data to a File
The a mode writes new data at the end of an existing file without removing its previous contents.
#include <stdio.h>
int main(void)
{
FILE *file = fopen("log.txt", "a");
if (file == NULL)
{
return 1;
}
fprintf(file, "New log entry\n");
fclose(file);
return 0;
}
Binary Files
C can also read and write binary data using fread and fwrite. Binary files store raw bytes rather than formatted text.
#include <stdio.h>
int main(void)
{
int numbers[] = {10, 20, 30, 40};
FILE *file = fopen("numbers.bin", "wb");
if (file == NULL)
{
return 1;
}
size_t count = sizeof numbers / sizeof numbers[0];
fwrite(numbers, sizeof numbers[0], count, file);
fclose(file);
return 0;
}
Reading Binary Data with fread
#include <stdio.h>
int main(void)
{
int numbers[4];
FILE *file = fopen("numbers.bin", "rb");
if (file == NULL)
{
return 1;
}
size_t count = fread(
numbers,
sizeof numbers[0],
4,
file
);
for (size_t i = 0; i < count; i++)
{
printf("%d\n", numbers[i]);
}
fclose(file);
return 0;
}
Closing a File with fclose
fclose closes an open file stream and flushes buffered output associated with the stream.
FILE *file = fopen("data.txt", "w");
if (file != NULL)
{
fputs("Hello\n", file);
fclose(file);
}
Checking for End of File
EOF is a special negative integer value used by input functions such as fgetc to indicate that no more characters can be read or that an input error occurred. feof and ferror can help distinguish the condition after an input operation.
int ch;
while ((ch = fgetc(file)) != EOF)
{
putchar(ch);
}
if (ferror(file))
{
printf("A file error occurred.\n");
}
File Position Functions
C provides functions such as fseek, ftell, and rewind for controlling and inspecting the current position in a file stream.
FILE *file = fopen("data.txt", "r");
if (file == NULL)
{
return 1;
}
fseek(file, 0, SEEK_END);
long size = ftell(file);
printf("File position: %ld\n", size);
rewind(file);
fclose(file);
Renaming and Removing Files
The standard C library provides rename and remove for basic file management operations.
#include <stdio.h>
int main(void)
{
if (rename("old.txt", "new.txt") != 0)
{
perror("rename");
}
if (remove("temporary.txt") != 0)
{
perror("remove");
}
return 0;
}
Text Files vs Binary Files
| Feature | Text File | Binary File |
|---|---|---|
| Content | Human-readable characters | Raw bytes |
| Common Functions | fgets, fputs, fprintf, fscanf | fread, fwrite |
| Typical Use | Logs and configuration | Structured binary data |
| Readability | Usually readable with a text editor | Usually not directly readable |
Common File Handling Mistakes
- Failing to check whether fopen returned NULL
- Forgetting to close an opened file
- Using the wrong file mode
- Overwriting a file accidentally with w mode
- Using an inappropriate buffer size
- Ignoring read and write errors
- Treating binary data as portable across all systems without considering representation
File Handling Best Practices
- Always check whether a file opened successfully
- Close files when they are no longer needed
- Choose the correct mode for the operation
- Check return values from important file operations
- Use fgets for safer line-oriented text input
- Use binary modes when working with binary data where required by the platform
- Keep file paths and permissions under control
Real-World Applications
- Log files
- Configuration files
- Data storage
- Report generation
- CSV and text processing
- Binary data processing
- Backup utilities
Practice Exercises
- Create a file and write five lines to it
- Read a text file line by line
- Count characters in a file
- Append log entries to a file
- Copy one file into another
- Store integers in a binary file
- Read a binary file and calculate the sum of its values
Conclusion
File handling gives C programs persistent storage and access to external data. By learning fopen, fclose, fgets, fputs, fprintf, fscanf, fread, fwrite, and file-position functions, you can build programs that reliably work with both text and binary files.