File Read & Write
Four ways to read and write
Once a file is open (see file handling basics for fopen/fclose), C gives you four ways to move data in and out. Each suits a different shape of data:
| Level | Write / Read | Best for |
|---|---|---|
| Character | fputc / fgetc | One char at a time |
| Line | fputs / fgets | Text lines |
| Formatted | fprintf / fscanf | Mixed values / records |
| Binary | fwrite / fread | Structs, arrays, raw data |
Character I/O: fgetc and fputc
fputc writes one character; fgetc reads one, returning EOF at the end of the file.
FILE *fp = fopen("data.txt", "w");
fputc('H', fp); fputc('i', fp); // write two chars
fclose(fp);
fp = fopen("data.txt", "r");
int ch;
while ((ch = fgetc(fp)) != EOF) // read till end
putchar(ch);
fclose(fp);Hi
Line I/O: fgets and fputs
fputs writes a string; fgets reads a line safely into a fixed buffer.
FILE *fp = fopen("note.txt", "w");
fputs("Hello file\n", fp);
fputs("Second line\n", fp);
fclose(fp);
fp = fopen("note.txt", "r");
char line[100];
while (fgets(line, sizeof(line), fp) != NULL)
printf("%s", line);
fclose(fp);Hello file
Second line
fgets takes the buffer size, so it never writes past your array. Prefer it over the old unsafe gets.
Formatted I/O: fscanf and fprintf
For records with mixed types (name, age, marks), fprintf and fscanf work like printf/scanf but on a file.
FILE *fp = fopen("rec.txt", "w");
fprintf(fp, "%s %d\n", "Aman", 95); // write a record
fclose(fp);
fp = fopen("rec.txt", "r");
char name[20]; int marks;
fscanf(fp, "%s %d", name, &marks); // read it back
printf("%s scored %d\n", name, marks);
fclose(fp);Aman scored 95
Binary I/O: fread and fwrite
To store a whole structure exactly as it sits in memory, use binary mode with fwrite and fread.
struct Student { char name[20]; int marks; };
struct Student s = {"Ravi", 88};
FILE *fp = fopen("s.dat", "wb"); // wb = write binary
fwrite(&s, sizeof(s), 1, fp);
fclose(fp);
struct Student r;
fp = fopen("s.dat", "rb"); // rb = read binary
fread(&r, sizeof(r), 1, fp);
printf("%s %d\n", r.name, r.marks);
fclose(fp);Ravi 88
Which method should you use?
- Character — copying files, counting characters, simple filters.
- Line — reading text files line by line (logs, config).
- Formatted — human-readable records with mixed fields.
- Binary — saving structs/arrays fast and compact, not for humans to read.
Common mistakes
- Comparing
fgetcto acharinstead ofint— EOF needs int. - Using text mode for binary data or the reverse.
- Reading with a different struct layout than you wrote (binary files are not portable across layouts).
- Forgetting to check the return value of read/write for errors.
Write three student records with fprintf, then read them all back in a loop with fscanf until it stops returning matches. Then try the same with fwrite/fread and compare the file sizes.
Summary
- C has four I/O levels: character, line, formatted and binary.
fgetc/fputchandle single characters; loop untilEOF.fgets/fputshandle lines safely.fprintf/fscanfhandle readable records;fwrite/freadhandle raw binary.- Choose the level that matches your data and whether it must be human-readable.
Frequently Asked Questions
What are the different ways to read and write files in C?
fgetc/fputc, line by line with fgets/fputs, formatted values with fscanf/fprintf, and raw binary blocks with fread/fwrite. You pick the one that matches the shape of your data.What is the difference between fprintf and fwrite?
fprintf writes human-readable text — numbers become characters like "42" — so the file can be opened in any editor. fwrite writes the raw bytes of the data exactly as they sit in memory, which is compact and fast but not readable as text. Use fprintf for text files and fwrite for binary files.What does fgets do in C?
fgets reads one line from a file into a character array, stopping at a newline or when the buffer is full, and it keeps the newline character. It is safer than older functions because you tell it the maximum size, so it will not overflow your buffer.When should I use fread and fwrite instead of fprintf?
fread/fwrite when you want to store data such as whole structures or arrays exactly as they are in memory — it is faster and smaller than text. Use fprintf/fscanf when you need the file to be human-readable or shared with other programs.How do you read a whole file character by character in C?
fgetc in a loop and stop when it returns the special value EOF, which marks the end of the file. Each call returns the next character, so the loop walks through the entire file one character at a time.