C File Handling: FILE* Handles, fopen(), fclose() & Text I/O Masterclass
Welcome to Phase 14 (Chapter 36): C File Handling โ FILE* Handles, fopen(), fclose() & Text I/O Masterclass! Disk file persistence allows C programs to store data permanently in non-volatile storage. In this guide, you will master C file streams (FILE*), operating system file descriptors, opening modes, and text I/O operations.
In C, disk files are accessed through abstract data structures called Streams managed by FILE* pointers declared in <stdio.h>. Instead of making expensive direct hardware calls for every character read or written, the C standard library maintains an internal Memory Stream Buffer in RAM.
Standard I/O streams automatically initialized on program startup include:
The 3 Standard Streams in C:
โข stdin: Standard Input Stream (Keyboard input by default, descriptor 0).
โข stdout: Standard Output Stream (Terminal screen output by default, descriptor 1).
โข stderr: Standard Error Stream (Unbuffered terminal error log output, descriptor 2).
The function fopen(const char *filename, const char *mode) opens a file stream and returns a pointer to a FILE structure. If the file cannot be opened (due to missing files, full disks, or permission denied), fopen() returns NULL.
| Mode Flag | Access Type | Behavior if File Exists | Behavior if File Missing |
|---|---|---|---|
"r" | Read Only | Opens file for reading at byte 0. | Returns NULL (Fails). |
"w" | Write Only | Truncates (erases) file to 0 bytes! | Creates new empty file. |
"a" | Append Only | Appends new data to end of file. | Creates new empty file. |
"r+" | Read & Write | Opens file for read/write at byte 0. | Returns NULL (Fails). |
"w+" | Read & Write | Truncates file to 0 bytes. | Creates new empty file. |
"a+" | Read & Append | Reads anywhere; writes always append to end. | Creates new empty file. |
๐ The Golden NULL Guard Rule:
NEVER perform file operations without checking if fopen() returned NULL! Dereferencing a NULL FILE* pointer immediately triggers a Segmentation Fault crash!
C provides 3 tiers of text I/O functions:
1. Character-by-Character: fgetc(fp) returns next character or EOF (-1); fputc(ch, fp) writes character.
2. Line-by-Line: fgets(buffer, size, fp) safely reads lines up to newline; fputs(str, fp) writes string.
3. Formatted I/O: fprintf(fp, "fmt", args) writes formatted text; fscanf(fp, "fmt", &args) parses formatted values.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char *filename = "students.txt";
// 1. WRITE DATA TO FILE
FILE *write_fp = fopen(filename, "w");
if (write_fp == NULL) {
perror("Error opening file for writing");
return EXIT_FAILURE;
}
fprintf(write_fp, "Ravi 85.5\n");
fprintf(write_fp, "Anitha 92.0\n");
fprintf(write_fp, "Kiran 78.2\n");
fclose(write_fp); // Flush buffers & close stream!
printf("Student records successfully written to %s\n\n", filename);
// 2. READ & PARSE DATA FROM FILE
FILE *read_fp = fopen(filename, "r");
if (read_fp == NULL) {
perror("Error opening file for reading");
return EXIT_FAILURE;
}
char name[50];
float marks;
int count = 0;
float total = 0.0f;
printf("--- READING STUDENT RECORDS ---\n");
while (fscanf(read_fp, "%49s %f", name, &marks) == 2) {
printf("Student %d: %-10s | Marks: %.1f\n", ++count, name, marks);
total += marks;
}
if (count > 0) {
printf("Average Class Marks: %.2f\n", total / count);
}
fclose(read_fp);
return EXIT_SUCCESS;
} Q1: Why must we always call fclose()?
Calling fclose() flushes any unwritten data remaining in the RAM stream buffer to physical disk and releases operating system kernel file descriptors.
Q2: What is the difference between fgets() and fscanf()?
fgets() reads an entire line including spaces safely until a newline character or buffer limit. fscanf() parses whitespace-separated formatted tokens.
Q3: What does EOF represent in C?
EOF is a macro constant (typically -1) returned by functions when the end of a file is reached or a read error occurs.
Q4: How do you force unwritten RAM buffers to disk immediately?
You can call fflush(fp); to force the C runtime library to flush all pending buffer contents directly to the OS kernel without closing the file handle.
Q5: What happens if you open an existing file with mode "w"?
The file is immediately truncated (cleared to 0 bytes length), completely erasing any pre-existing data inside it!