File Handling in C
Read and write files! Learn fopen, fclose, fprintf, fscanf, and more. Save data permanently and load it back.
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
| Function | Purpose | Header |
|---|---|---|
| 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):
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:
💡 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
1#include <stdio.h>23int main() {4 // Open file for reading5 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}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
| Mode | Description | If File Exists | If File Not Exists |
|---|---|---|---|
| "r" | Read only | Open from start | Error (NULL) |
| "w" | Write only | Erase content! | Create new |
| "a" | Append only | Write at end | Create new |
| "r+" | Read + Write | Open from start | Error (NULL) |
| "w+" | Read + Write | Erase content! | Create new |
| "a+" | Read + Append | Read any, write at end | Create 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
1#include <stdio.h>23int 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 character10 }11 12 fclose(file);13 return 0;14}Method 2: fgets() - Read Line by Line (Recommended)
1#include <stdio.h>23int 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 full10 while (fgets(line, sizeof(line), file) != NULL) {11 printf("%s", line); // line includes \n12 }13 14 fclose(file);15 return 0;16}Method 3: fscanf() - Formatted Reading
1#include <stdio.h>23int 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}Name: Alice, Age: 20, Grade: 3.8
06Writing Text Files
Method 1: fputc() - Write Character
1#include <stdio.h>23int 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
1#include <stdio.h>23int 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)
1#include <stdio.h>23int 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}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
1#include <stdio.h>23struct Student {4 char name[50];5 int age;6 float grade;7};89int main() {10 struct Student s1 = {"Alice", 20, 3.8};11 12 // Write struct to binary file13 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 back20 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}Name: Alice, Age: 20, Grade: 3.8
Write and Read Array
1#include <stdio.h>23int main() {4 int arr[] = {10, 20, 30, 40, 50};5 int n = 5;6 7 // Write array8 FILE *file = fopen("numbers.bin", "wb");9 fwrite(arr, sizeof(int), n, file);10 fclose(file);11 12 // Read array13 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}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:
| Function | Purpose | Syntax |
|---|---|---|
| fseek() | Move to position | fseek(file, offset, origin) |
| ftell() | Get current position | long pos = ftell(file) |
| rewind() | Go to start | rewind(file) |
fseek() Origin Constants
| Constant | Value | Meaning |
|---|---|---|
| SEEK_SET | 0 | Beginning of file |
| SEEK_CUR | 1 | Current position |
| SEEK_END | 2 | End of file |
1#include <stdio.h>23int main() {4 FILE *file = fopen("data.txt", "r");5 if (file == NULL) return 1;6 7 // Get file size8 fseek(file, 0, SEEK_END); // Go to end9 long size = ftell(file); // Get position = size10 printf("File size: %ld bytes\n", size);11 12 // Go back to start13 rewind(file); // Same as fseek(file, 0, SEEK_SET)14 15 // Read first character16 int ch = fgetc(file);17 printf("First char: %c\n", ch);18 19 // Skip 5 characters from current position20 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
| Function | Purpose |
|---|---|
| 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 |
1#include <stdio.h>23int 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 ended17 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}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: