Chapter 25Advanced

File Handling in C

Read and write files! Learn fopen, fclose, fprintf, fscanf, and more. Save data permanently and load it back.

25 min readUpdated 2024-12-16
filefopenfclosefreadfwritefprintffscanfFILE

What You Will Learn

  • Open files with different modes (r, w, a)
  • Read and write text files
  • Handle binary files
  • Check for errors when working with files

01What is File Handling?

📁 Why Files?

Variables store data in RAM - they disappear when your program ends! Files store data on disk - data persists even after the program closes.

📝 Text Files

  • • Human-readable content
  • • Each line ends with newline
  • • Examples: .txt, .csv, .html
  • • Use: fgets, fputs, fprintf, fscanf

💾 Binary Files

  • • Raw bytes, not readable
  • • Exact memory representation
  • • Examples: .exe, .bin, .dat
  • • Use: fread, fwrite
FunctionPurposeHeader
fopen()Open a file<stdio.h>
fclose()Close a file<stdio.h>
fgets() / fputs()Read/write string (line)<stdio.h>
fgetc() / fputc()Read/write single char<stdio.h>
fprintf() / fscanf()Formatted read/write<stdio.h>
fread() / fwrite()Binary read/write<stdio.h>
fseek() / ftell()File position<stdio.h>

02The FILE Structure

📚 What is FILE?

FILE is a structure defined in <stdio.h>. It contains information about the file being accessed. You never access its members directly - you always use FILE * (a pointer) and functions like fopen, fread, etc.

The FILE structure contains (simplified):

struct FILE {

char *buffer; /* Data buffer */

int bufferSize; /* Size of buffer */

char *currentPos; /* Current position in buffer */

int fileDescriptor; /* OS file handle */

int mode; /* Read/write mode */

int eof; /* End-of-file indicator */

int error; /* Error indicator */

};

How file operations work:

Your Program
↓ FILE * pointer ↓
FILE Structure (Buffer)
↓ System Calls ↓
Operating System
↓ Hardware ↓
Disk (HDD/SSD)

💡 Why Buffering?

Disk operations are slow. The buffer collects data and writes/reads in larger chunks, making file operations much faster.

03Opening & Closing Files

📝 fopen() Syntax

FILE *fopen(const char *filename, const char *mode);

  • filename: Path to the file
  • mode: How to open (read, write, append, etc.)
  • Returns: FILE pointer, or NULL if failed
open_close.c
C
1#include <stdio.h>
2
3int main() {
4 // Open file for reading
5 FILE *file = fopen("data.txt", "r");
6
7 // Always check if file opened!
8 if (file == NULL) {
9 printf("Error: Cannot open file!\n");
10 return 1;
11 }
12
13 printf("File opened successfully!\n");
14
15 // Always close when done!
16 fclose(file);
17
18 return 0;
19}
Output

File opened successfully!

⚠️ Always Close Files!

Not closing files can cause: data loss (buffer not flushed), resource leaks, and file locks. Always use fclose()!

04File Modes

ModeDescriptionIf File ExistsIf File Not Exists
"r"Read onlyOpen from startError (NULL)
"w"Write onlyErase content!Create new
"a"Append onlyWrite at endCreate new
"r+"Read + WriteOpen from startError (NULL)
"w+"Read + WriteErase content!Create new
"a+"Read + AppendRead any, write at endCreate new

💾 Binary Mode

Add "b" for binary files: "rb", "wb", "ab", etc.

Text Mode (default)

"r", "w", "a"

Newline translations happen

Binary Mode

"rb", "wb", "ab"

Raw bytes, no translation

05Reading Text Files

Method 1: fgetc() - Read Character by Character

read_char.c
C
1#include <stdio.h>
2
3int main() {
4 FILE *file = fopen("data.txt", "r");
5 if (file == NULL) return 1;
6
7 int ch;
8 while ((ch = fgetc(file)) != EOF) {
9 putchar(ch); // Print character
10 }
11
12 fclose(file);
13 return 0;
14}

Method 2: fgets() - Read Line by Line (Recommended)

read_line.c
C
1#include <stdio.h>
2
3int main() {
4 FILE *file = fopen("data.txt", "r");
5 if (file == NULL) return 1;
6
7 char line[256];
8
9 // fgets reads until newline or buffer full
10 while (fgets(line, sizeof(line), file) != NULL) {
11 printf("%s", line); // line includes \n
12 }
13
14 fclose(file);
15 return 0;
16}

Method 3: fscanf() - Formatted Reading

read_formatted.c
C
1#include <stdio.h>
2
3int main() {
4 FILE *file = fopen("students.txt", "r");
5 if (file == NULL) return 1;
6
7 char name[50];
8 int age;
9 float grade;
10
11 // File contains: "Alice 20 3.8"
12 while (fscanf(file, "%s %d %f", name, &age, &grade) == 3) {
13 printf("Name: %s, Age: %d, Grade: %.1f\n", name, age, grade);
14 }
15
16 fclose(file);
17 return 0;
18}
Output

Name: Alice, Age: 20, Grade: 3.8

06Writing Text Files

Method 1: fputc() - Write Character

write_char.c
C
1#include <stdio.h>
2
3int main() {
4 FILE *file = fopen("output.txt", "w");
5 if (file == NULL) return 1;
6
7 fputc('H', file);
8 fputc('i', file);
9 fputc('!', file);
10 fputc('\n', file);
11
12 fclose(file);
13 printf("Written to output.txt\n");
14 return 0;
15}

Method 2: fputs() - Write String

write_string.c
C
1#include <stdio.h>
2
3int main() {
4 FILE *file = fopen("output.txt", "w");
5 if (file == NULL) return 1;
6
7 fputs("Hello, World!\n", file);
8 fputs("This is line 2\n", file);
9
10 fclose(file);
11 return 0;
12}

Method 3: fprintf() - Formatted Writing (Most Used)

write_formatted.c
C
1#include <stdio.h>
2
3int main() {
4 FILE *file = fopen("report.txt", "w");
5 if (file == NULL) return 1;
6
7 char name[] = "Alice";
8 int age = 25;
9 float score = 95.5;
10
11 // Just like printf, but to file!
12 fprintf(file, "Name: %s\n", name);
13 fprintf(file, "Age: %d\n", age);
14 fprintf(file, "Score: %.1f\n", score);
15
16 fclose(file);
17 printf("Report saved!\n");
18 return 0;
19}
report.txt

Name: Alice

Age: 25

Score: 95.5

07Binary Files

💾 When to Use Binary?

Use binary for structs, arrays, images, or any raw data. Binary is faster and more compact than text, but not human-readable.

📝 fwrite() and fread() Syntax

fwrite(ptr, size, count, file);

fread(ptr, size, count, file);

  • ptr: Pointer to data
  • size: Size of each element
  • count: Number of elements
  • file: FILE pointer

Write and Read a Struct

binary_struct.c
C
1#include <stdio.h>
2
3struct Student {
4 char name[50];
5 int age;
6 float grade;
7};
8
9int main() {
10 struct Student s1 = {"Alice", 20, 3.8};
11
12 // Write struct to binary file
13 FILE *file = fopen("student.dat", "wb");
14 if (file == NULL) return 1;
15
16 fwrite(&s1, sizeof(struct Student), 1, file);
17 fclose(file);
18
19 // Read struct back
20 struct Student s2;
21 file = fopen("student.dat", "rb");
22 if (file == NULL) return 1;
23
24 fread(&s2, sizeof(struct Student), 1, file);
25 fclose(file);
26
27 printf("Name: %s, Age: %d, Grade: %.1f\n",
28 s2.name, s2.age, s2.grade);
29
30 return 0;
31}
Output

Name: Alice, Age: 20, Grade: 3.8

Write and Read Array

binary_array.c
C
1#include <stdio.h>
2
3int main() {
4 int arr[] = {10, 20, 30, 40, 50};
5 int n = 5;
6
7 // Write array
8 FILE *file = fopen("numbers.bin", "wb");
9 fwrite(arr, sizeof(int), n, file);
10 fclose(file);
11
12 // Read array
13 int loaded[5];
14 file = fopen("numbers.bin", "rb");
15 fread(loaded, sizeof(int), n, file);
16 fclose(file);
17
18 for (int i = 0; i < n; i++) {
19 printf("%d ", loaded[i]);
20 }
21
22 return 0;
23}
Output

10 20 30 40 50

08File Positioning

Files have an internal position indicator that tracks where the next read/write will happen. You can move this position using:

FunctionPurposeSyntax
fseek()Move to positionfseek(file, offset, origin)
ftell()Get current positionlong pos = ftell(file)
rewind()Go to startrewind(file)

fseek() Origin Constants

ConstantValueMeaning
SEEK_SET0Beginning of file
SEEK_CUR1Current position
SEEK_END2End of file
file_position.c
C
1#include <stdio.h>
2
3int main() {
4 FILE *file = fopen("data.txt", "r");
5 if (file == NULL) return 1;
6
7 // Get file size
8 fseek(file, 0, SEEK_END); // Go to end
9 long size = ftell(file); // Get position = size
10 printf("File size: %ld bytes\n", size);
11
12 // Go back to start
13 rewind(file); // Same as fseek(file, 0, SEEK_SET)
14
15 // Read first character
16 int ch = fgetc(file);
17 printf("First char: %c\n", ch);
18
19 // Skip 5 characters from current position
20 fseek(file, 5, SEEK_CUR);
21 ch = fgetc(file);
22 printf("6th char: %c\n", ch);
23
24 fclose(file);
25 return 0;
26}

09Error Handling

FunctionPurpose
feof(file)Returns non-zero if end-of-file reached
ferror(file)Returns non-zero if error occurred
clearerr(file)Clear error and EOF flags
perror("msg")Print error message
error_handling.c
C
1#include <stdio.h>
2
3int main() {
4 FILE *file = fopen("missing.txt", "r");
5
6 if (file == NULL) {
7 perror("Error opening file");
8 return 1;
9 }
10
11 char buffer[100];
12 while (fgets(buffer, sizeof(buffer), file) != NULL) {
13 printf("%s", buffer);
14 }
15
16 // Check why loop ended
17 if (feof(file)) {
18 printf("\nEnd of file reached.\n");
19 }
20 if (ferror(file)) {
21 printf("\nError reading file!\n");
22 }
23
24 fclose(file);
25 return 0;
26}
Output (if file missing)

Error opening file: No such file or directory

10Common Mistakes

❌ Not Checking fopen() Return

FILE *f = fopen("x.txt", "r");

fprintf(f, "Hi"); // Crash if NULL!

FILE *f = fopen("x.txt", "r");

if (f == NULL) return 1;

❌ Forgetting to Close File

Always fclose(file) to flush buffer and release resources.

❌ Using "w" Instead of "a"

"w" erases existing content! Use "a" to append without erasing.

❌ Wrong Mode for Binary

Always use "rb"/"wb" for binary files. Text mode can corrupt binary data!

11Summary

🎯 Key Takeaways

  • FILE *: Pointer to file structure, never access directly
  • fopen/fclose: Always open and close files properly
  • Text: fgets, fputs, fprintf, fscanf
  • Binary: fread, fwrite with "rb"/"wb" mode
  • Positioning: fseek, ftell, rewind
  • Errors: Check NULL, use perror, feof, ferror

FILE *file = fopen("data.txt", "r");

if (file == NULL) { perror("Error"); return 1; }

fclose(file);

10Next Steps

Learn about the C standard libraries: