Structures, Files & More
File Handling
Save data that outlives your program: open, write, read, append and close text files with fopen, fprintf, fscanf, fgets and friends.
Variables vanish when a program ends. Files keep data on disk. C works with files through a FILE * pointer from stdio.h.
The pattern is always the same: open → read or write → close.
Opening a file
C
FILE *fp = fopen("marks.txt", "w");
if (fp == NULL) { perror("fopen"); return 1; } // always check!| Mode | Meaning | If the file exists | If it does not |
|---|---|---|---|
"r" |
read | read from the start | fails (returns NULL) |
"w" |
write | erases it | creates it |
"a" |
append | adds at the end | creates it |
"r+" |
read and write | opens it | fails |
"w+" |
read and write | erases it | creates it |
"a+" |
read and append | opens it | creates it |
Add b for binary files: "rb", "wb".
Writing and reading text
C
#include <stdio.h>
int main(void) {
FILE *fp = fopen("marks.txt", "w");
if (!fp) { perror("marks.txt"); return 1; }
fprintf(fp, "%s %d\n", "Asha", 91);
fprintf(fp, "%s %d\n", "Ravi", 78);
fprintf(fp, "%s %d\n", "Meera", 85);
fclose(fp);
printf("Saved 3 records.\n");
fp = fopen("marks.txt", "r");
if (!fp) { perror("marks.txt"); return 1; }
char name[20];
int marks, total = 0, count = 0;
while (fscanf(fp, "%19s %d", name, &marks) == 2) { // stop when a read fails
printf("%-6s %d\n", name, marks);
total += marks;
count++;
}
fclose(fp);
printf("Class average: %.2f\n", (double)total / count);
return 0;
}Output
Saved 3 records. Asha 91 Ravi 78 Meera 85 Class average: 84.67
Line by line with fgets, and appending
C
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *fp = fopen("diary.txt", "w");
fputs("Monday: started C file handling\n", fp);
fclose(fp);
fp = fopen("diary.txt", "a"); // append keeps the old content
fputs("Tuesday: wrote my first log file\n", fp);
fclose(fp);
char line[100];
int n = 0;
fp = fopen("diary.txt", "r");
while (fgets(line, sizeof line, fp) != NULL) {
line[strcspn(line, "\n")] = '\0';
printf("%d | %s\n", ++n, line);
}
fclose(fp);
return 0;
}Output
1 | Monday: started C file handling 2 | Tuesday: wrote my first log file
Character by character: copy a file and count stats
C
#include <stdio.h>
int main(void) {
FILE *out = fopen("source.txt", "w");
fputs("Files are just bytes.\nRead them one char at a time!\n", out);
fclose(out);
FILE *in = fopen("source.txt", "r");
FILE *copy = fopen("copy.txt", "w");
int ch, chars = 0, lines = 0, words = 0, inWord = 0;
while ((ch = fgetc(in)) != EOF) { // ch must be int to hold EOF
fputc(ch, copy);
chars++;
if (ch == '\n') lines++;
if (ch == ' ' || ch == '\n' || ch == '\t') inWord = 0;
else if (!inWord) { inWord = 1; words++; }
}
fclose(in);
fclose(copy);
printf("chars %d, words %d, lines %d\n", chars, words, lines);
return 0;
}Output
chars 52, words 11, lines 2
Binary files: saving structures
fwrite and fread copy raw bytes, which makes saving whole structures easy and fast:
C
#include <stdio.h>
typedef struct { int id; char item[16]; double price; } Product;
int main(void) {
Product stock[3] = {{1, "Notebook", 45.0}, {2, "Pen", 10.5}, {3, "Calculator", 799.0}};
FILE *fp = fopen("stock.dat", "wb");
fwrite(stock, sizeof(Product), 3, fp);
fclose(fp);
Product p;
fp = fopen("stock.dat", "rb");
fseek(fp, 2 * sizeof(Product), SEEK_SET); // jump straight to record #3
fread(&p, sizeof(Product), 1, fp);
printf("Record 3: %s costs Rs %.2f\n", p.item, p.price);
rewind(fp); // back to the start
fread(&p, sizeof(Product), 1, fp);
printf("Record 1: %s\n", p.item);
fclose(fp);
return 0;
}Output
Record 3: Calculator costs Rs 799.00 Record 1: Notebook
| Function | Purpose |
|---|---|
fopen, fclose |
open and close |
fprintf, fscanf |
formatted write / read |
fputs, fgets |
write / read a line |
fputc, fgetc |
write / read one character |
fwrite, fread |
write / read raw blocks (binary) |
fseek, ftell, rewind |
move around in a file |
feof, ferror |
check for end of file or an error |
Test yourself
4 questions · pick an answer to check it instantly
- 1
Which mode opens a file for writing without erasing its current contents?
Append mode adds new data at the end and creates the file if needed. - 2
What does
fopenreturn if the file cannot be opened?Always compare the result withNULLbefore using it. - 3
Why should the variable receiving
fgetc(fp)be anint?Storing the result incharcan make a real character look likeEOF, or makeEOFundetectable. - 4
Which function moves the file position to a specific byte offset?
fseek(fp, offset, SEEK_SET)jumps tooffsetbytes from the start.ftellreports the current position.