File Handling (Lesson)
File Handling in C
In C programming, a file is a place on the disk where a group of related data is stored. File handling allows you to create, update, read, and delete the data stored in files.
1. Why do we need Files?
- Data Persistence: When a program terminates, the data in variables is lost. Storing data in a file preserves it for future use.
- Handling Large Data: Entering thousands of records manually every time a program runs is inefficient. Files allow you to read bulk data instantly.
- Portability: You can easily transfer files from one computer to another without changing the program logic.
2. Types of Files
In C, you can deal with two main types of files:
A. Text Files (.txt)
- Store data in plain text (ASCII/Unicode).
- Can be opened and read using any text editor (Notepad, VS Code).
- Pros: Easy to maintain, readable, and portable across platforms.
- Cons: Less secure and takes up more storage space.
B. Binary Files (.bin, .dat)
- Store data in binary format (0s and 1s), exactly as it appears in memory.
- Cannot be read easily with standard text editors.
- Pros: High storage efficiency, better security, and faster access for large datasets.
- Cons: Not human-readable without a specialized program.
3. Working with Files
To work with files, you must declare a pointer of type FILE. This pointer acts as a bridge between the program and the file stored on the disk.
FILE *fp;
3.1. Opening and Closing a File
- Opening:
fp = fopen("filename", "mode"); - Closing:
fclose(fp);(Always close files to release memory resources).
File Modes
| Mode | Meaning | Explanation |
|---|---|---|
"r"/"rb" | Read | Opens a text/binary file for reading. Returns NULL if not found. |
"w"/"wb" | Write | Creates a file or overwrites an existing one for writing. |
"a"/"ab" | Append | Opens or creates a file for adding data at the end. |
"r+"/"rb+" | Read/Write | Opens for both reading and writing. |
4. Reading and Writing to Files
4.1. Text File I/O (fprintf & fscanf)
These functions are similar to printf and scanf, but they work with files.
Example: Writing a number to a file
#include <stdio.h>
#include <stdlib.h>
int main() {
int num;
FILE *fptr = fopen("program.txt", "w");
if (fptr == NULL) {
printf("Error! File could not be opened.");
exit(1);
}
printf("Enter a number: ");
scanf("%d", &num);
fprintf(fptr, "%d", num);
fclose(fptr);
return 0;
}
4.2. Binary File I/O (fwrite & fread)
Binary files use fwrite and fread to store and retrieve entire blocks of memory (like structures).
Syntax:
fwrite(address_of_data, size_of_data, number_of_records, file_pointer);
fread(address_to_store, size_of_data, number_of_records, file_pointer);
Example: Storing a Structure
#include <stdio.h>
struct Record {
int id;
char name[20];
};
int main() {
FILE *fp = fopen("data.bin", "wb");
struct Record r1 = {1, "Project A"};
fwrite(&r1, sizeof(struct Record), 1, fp);
fclose(fp);
return 0;
}
5. Random Access in Files (fseek, ftell, rewind)
Sometimes, instead of reading a file from the beginning, you need to jump to a specific record.
fseek(): Moves the file pointer to a specific location.fseek(fp, offset, SEEK_SET);// Start from beginningfseek(fp, offset, SEEK_CUR);// Start from current positionfseek(fp, offset, SEEK_END);// Start from end
ftell(): Tells you the current position of the pointer (in bytes).rewind(): Quickly moves the pointer back to the very beginning.
Example: Reading Records in Reverse
#include <stdio.h>
#include <stdlib.h>
struct Data {
int n1;
};
int main() {
FILE *fptr = fopen("numbers.bin", "rb");
struct Data d;
// Move to the very last record
fseek(fptr, -sizeof(struct Data), SEEK_END);
// Read and then move back two steps to simulate reverse reading
for(int i = 0; i < 5; ++i) {
fread(&d, sizeof(struct Data), 1, fptr);
printf("Value: %d\n", d.n1);
fseek(fptr, -2 * sizeof(struct Data), SEEK_CUR);
}
fclose(fptr);
return 0;
}
7. Practical Examples & Mini-Projects
Here are several practical scenarios to help you master file handling.
Example A: Counting Characters, Words, and Lines
This program reads a text file and counts its contents. This is a common logic used in text editors.
#include <stdio.h>
int main() {
FILE *fp;
char ch;
int chars = 0, words = 0, lines = 0;
fp = fopen("article.txt", "r");
if (fp == NULL) return 1;
while ((ch = fgetc(fp)) != EOF) {
chars++;
if (ch == '\n' || ch == '\0') lines++;
if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\0') words++;
}
if (chars > 0) {
lines++; // Count the last line
words++; // Count the last word
}
printf("Characters: %d\n", chars);
printf("Words: %d\n", words);
printf("Lines: %d\n", lines);
fclose(fp);
return 0;
}
Example B: Copying One File to Another
A simple "file cloning" program. It reads from a source and writes to a destination.
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *source, *dest;
char ch;
source = fopen("source.txt", "r");
if (source == NULL) exit(1);
dest = fopen("destination.txt", "w");
if (dest == NULL) {
fclose(source);
exit(1);
}
while ((ch = fgetc(source)) != EOF) {
fputc(ch, dest);
}
printf("File copied successfully.\n");
fclose(source);
fclose(dest);
return 0;
}
Example C: Appending Data (The "Logger" Pattern)
This example shows how to add data to the end of a file without deleting the old content using "a" mode.
#include <stdio.h>
#include <time.h>
int main() {
FILE *logFile;
logFile = fopen("log.txt", "a");
if (logFile == NULL) return 1;
// Get current time
time_t now = time(NULL);
char *time_str = ctime(&now);
fprintf(logFile, "Program accessed at: %s", time_str);
printf("Access time logged.\n");
fclose(logFile);
return 0;
}
8. Persistence Mini-Project: Student Database
This example demonstrates a tiny database where you can add records and then view them all later.
#include <stdio.h>
struct Student {
int id;
char name[30];
float marks;
};
void addRecord() {
FILE *fp = fopen("students.db", "ab");
struct Student s;
printf("Enter ID, Name, and Marks: ");
scanf("%d %s %f", &s.id, s.name, &s.marks);
fwrite(&s, sizeof(struct Student), 1, fp);
fclose(fp);
}
void displayRecords() {
FILE *fp = fopen("students.db", "rb");
struct Student s;
printf("\n--- Student List ---\n");
while (fread(&s, sizeof(struct Student), 1, fp)) {
printf("ID: %d | Name: %-10s | Marks: %.2f\n", s.id, s.name, s.marks);
}
fclose(fp);
}
int main() {
int choice;
while(1) {
printf("\n1. Add Record\n2. Display All\n3. Exit\nChoice: ");
scanf("%d", &choice);
if(choice == 1) addRecord();
else if(choice == 2) displayRecords();
else break;
}
return 0;
}