File Handling Basics
Data that outlives the programVariables disappear when a program ends — files do not. In the lab below you see the file on the disk next to your program: fopen it in different modes, write with fprintf, read it back with fscanf, fgetc and fgets, watch the file position move, and find out what happens when the file is missing.
- fopenopens a file — or returns NULL
- 'w' / 'a'empty and write / add at the end
- EOFmarks the end of the file
Ready
Keyboard: ← → step · Space play / pause · R reset · Esc exit classroom mode
The ideas behind the lab
Exactly what you watched happen, in plain steps.
Open, use, close
Working with a file always follows the same three steps. fopen(name, mode) opens it and returns a FILE * — a pointer to a structure that remembers the file and the current position — or NULL when it fails. Then you read or write with functions that look like the console ones with an f in front (fprintf, fscanf, fgets, fputs, fgetc, fputc). Finally fclose writes out anything still waiting and releases the file.
FILE *fp = fopen("data.txt", "w"); // 1. open
if (fp == NULL) { // always check!
perror("data.txt");
return 1;
}
fprintf(fp, "%d\n", 42); // 2. use
fclose(fp); // 3. close
| Mode | Meaning | File must exist? | Old content |
|---|---|---|---|
| "r" | read | yes — else NULL | kept |
| "w" | write | no — it is created | ERASED |
| "a" | append (write at the end) | no — it is created | kept |
| "r+" | read and write | yes | kept |
| "w+" | read and write | no | erased |
| "a+" | read, and write at the end | no | kept |
Opening and closing
- FILE *fp = fopen("name.txt", "r"); — FILE is declared in stdio.h.
- fopen returns NULL if the file is missing ("r"), the folder is wrong or access is denied.
- perror("name.txt") prints why, e.g. "name.txt: No such file or directory".
- fclose(fp) flushes the data to disk and frees the FILE.
- A program can only have a limited number of files open — close them when done.
Writing text
- fprintf(fp, format, …) — printf into a file.
- fputs("text", fp) writes a string (no newline added).
- fputc('A', fp) writes one character.
- "w" starts with an empty file; "a" adds to the end.
- Writes are buffered: they reach the disk at fclose (or fflush).
Reading text and EOF
- fscanf(fp, "%d", &n) returns how many values it read — or EOF at the end.
- fgets(line, sizeof line, fp) reads one line (with '\n') or returns NULL at the end.
- fgetc(fp) returns the next character as an int, or EOF (−1).
- Loop on the read function's result: while (fgets(…) != NULL).
- Each read moves the file position forward; it starts at 0 for "r".
A small diary: append a line, then read them all
Every line, explained.
#include <stdio.h>
int main(void)
{
FILE *fp = fopen("diary.txt", "a");
Creates the file the first time, adds to it afterwards.
if (fp == NULL) {
perror("diary.txt");
Prints the reason the file could not be opened.
return 1;
}
fprintf(fp, "Learned files in C\n");
fclose(fp);
fp = fopen("diary.txt", "r");
Open again, now for reading, at position 0.
if (fp == NULL) return 1;
char line[100];
int n = 0;
while (fgets(line, sizeof line, fp) != NULL)
One line per round, until NULL.
printf("%d: %s", ++n, line);
line already ends with '\n'.
fclose(fp);
printf("%d entries\n", n);
Grows by one every time you run the program.
return 0;
}
Spot the bug
Mistakes almost every beginner makes — and how to fix them.
Not checking fopen
FILE *fp = fopen("data.txt", "r");
fscanf(fp, "%d", &n); // crash if fp is NULL
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) { perror("data.txt"); return 1; }
Missing files are normal. Using a NULL FILE * crashes the program.
Using "w" when you meant "a"
fopen("log.txt", "w"); // old log erased
fopen("log.txt", "a"); // add to the end
"w" empties the file the moment it is opened.
while (!feof(fp))
while (!feof(fp)) {
fscanf(fp, "%d", &n); // last value counted twice
sum += n;
}
while (fscanf(fp, "%d", &n) == 1)
sum += n;
feof only becomes true AFTER a read has failed. Test the read itself.
Storing fgetc in a char
char c; while ((c = fgetc(fp)) != EOF)
int c; while ((c = fgetc(fp)) != EOF)
EOF is −1, an int. In a char it can be confused with a real character or never match.
Forgetting fclose
fprintf(fp, "%d", total); return 0; // data may never reach the disk
fprintf(fp, "%d", total); fclose(fp); return 0;
Writes are buffered. Close (or fflush) to be sure they are saved.
Check your understanding
Answer each question — you will see the explanation straight away.
What does fopen return when the file cannot be opened?
Always compare the FILE * with NULL.
A file holds "old". It is opened with "w" and "new" is written. What does it hold?
"w" empties the file first.
The same file holding "old" is opened with "a" and "new" is written. What does it hold?
"a" writes at the end and keeps the old content.
What does fgets return at the end of the file?
fgets returns NULL; fgetc and fscanf return EOF.
Why should the variable that receives fgetc be an int?
fgetc returns 0–255 for characters and −1 for EOF.
File Handling Basics quiz
Test yourself: 10 questions, 70% to pass. Create a free account to take the quiz, save your progress and work towards the certificate.