C ProgrammingUnit 1011 min read
File Handling in C: Modes, Operations, and Applications
Unit 10 of C Programming covers file handling fundamentals—opening/closing files, reading/writing data, modes (r, w, a, r+), error handling, and practical applications like data storage, logs, and configuration files. Learn with real-world examples (e.g., eSewa transactions, Daraz order logs) and step-by-step code trac
TAKEAWAYS:
- Files in C are accessed via file pointers (
FILE *) using functions likefopen(),fclose(),fprintf(), andfscanf(). - Modes (
r,w,a,r+,w+,a+) determine how files are opened (read/write/append) and whether they truncate existing data. - Error handling is critical: always check if
fopen()returnsNULLto avoid crashes. - Binary vs. text mode (
"rb","wb") affects how data (e.g., images, serialized objects) is stored/retrieved. - Real-world uses include transaction logs (eSewa), user data storage (Khalti), and configuration files (Pathao’s ride algorithms).
- Sequential vs. random access: Use
fseek()to jump to specific positions in files (e.g., updating a record in a database).
1. Introduction to File Handling
Files are persistent data storage units outside a program’s memory. In C, files are handled using stream-oriented functions from <stdio.h>. Key concepts:
- Text files: Store characters (e.g.,
.txt,.csv). - Binary files: Store raw data (e.g.,
.dat, images, executables). - File streams: Connections between a program and a file (e.g.,
stdin,stdout,stderr).
Why Use Files?
- Persistence: Data survives after the program closes (e.g., saving user profiles in Khalti).
- Large data: RAM is limited; files store datasets (e.g., NTC’s electricity usage records).
- Sharing: Multiple programs can access the same file (e.g., Daraz’s order history).
2. File Modes and Their Differences
The mode string in fopen() defines how a file is opened. Common modes:
| Mode | Description | Example Use Case |
|---|---|---|
"r" |
Open for reading (fails if file doesn’t exist). | Reading a config file (e.g., Pathao’s API keys). |
"w" |
Open for writing (creates file; truncates existing data). | Overwriting a log file (e.g., Ncell’s call logs). |
"a" |
Open for appending (creates file if missing; adds to end). | Adding new transactions to eSewa’s ledger. |
"r+" |
Open for reading and writing (does not truncate). | Editing a user’s order history (Daraz). |
"w+" |
Open for reading and writing (truncates existing data). | Rewriting a database backup. |
"a+" |
Open for reading and appending. | Updating a shared blacklist (e.g., spam emails). |
Key Differences: Append ("a") vs. Write ("w")
flowchart TD
A["File exists?"] -->|"Yes"| B["Mode 'w'"]
B --> C["Truncates file\nOverwrites data"]
A -->|"No"| D["Mode 'w'"]
D --> E["Creates new file"]
A -->|"Yes"| F["Mode 'a'"]
F --> G["Appends data\nKeeps existing content"]
A -->|"No"| H["Mode 'a'"]
H --> I["Creates new file"]Example:
"w": Writing"Hello"totest.txt(then"World") → File contains only"World"."a": Writing"Hello"(then"World") → File contains"HelloWorld".
3. File Operations: Opening, Closing, and Reading/Writing
Step 1: Opening a File
FILE *file_ptr = fopen("data.txt", "r");
if (file_ptr == NULL) {
printf("Error opening file!\n");
exit(1);
}
Visual: File Pointer State
Step 2: Reading/Writing Data
- Text mode: Use
fscanf()/fprintf()(e.g., reading integers as%d). - Binary mode: Use
fread()/fwrite()(e.g., reading a struct byte-by-byte).
Example: Writing to a File
FILE *fp = fopen("output.txt", "w");
fprintf(fp, "Hello, TU!\n");
fclose(fp);
State After Execution:
Step 3: Closing a File
Always close files to free system resources:
fclose(fp); // Returns 0 on success, EOF on failure.
4. Real-World Applications
Example 1: eSewa Transaction Logs
- Idea Used: Append mode (
"a") to log transactions without losing old data. - How It Works:
- Each payment is appended to
transactions.logwith timestamp, user ID, and amount. - Code snippet:
FILE *log = fopen("transactions.log", "a"); fprintf(log, "%s: User %d paid Rs. %d\n", time_str, user_id, amount); fclose(log); - Visual:
flowchart LR A["User pays via eSewa"] --> B["Append to transactions.log"] B --> C["File grows: Rs. 500\nRs. 300\n..."]
- Each payment is appended to
Example 2: Daraz Order Queue
- Idea Used: Random access (
fseek()) to update order statuses. - How It Works:
- Orders are stored in
orders.datas binary records (structs). - When an order is shipped, its status is updated at a specific byte offset.
- Code snippet:
typedef struct { int id; char status[20]; } Order; Order order; FILE *fp = fopen("orders.dat", "r+"); fseek(fp, id * sizeof(Order), SEEK_SET); // Jump to order #id fread(&order, sizeof(Order), 1, fp); strcpy(order.status, "Shipped"); fseek(fp, -sizeof(Order), SEEK_CUR); fwrite(&order, sizeof(Order), 1, fp); fclose(fp);
- Orders are stored in
Example 3: NTC Electricity Billing
- Idea Used: Text files (
"r+"mode) to read/update customer data. - How It Works:
- Customer records (ID, name, units consumed) are stored in
billing.csv. - When a new reading is taken, the file is opened in
"r+", the record is located, and updated. - Visual:
flowchart TD A["Read billing.csv"] --> B["Find customer ID 101"] B --> C["Update units\nfrom 200 to 250"] C --> D["Save changes"]
- Customer records (ID, name, units consumed) are stored in
5. Error Handling in File Operations
Always check for errors:
fopen()failure: ReturnsNULLif file cannot be opened.- Read/write failures: Check return values of
fscanf(),fprintf(), etc. - End-of-file:
feof()detects when reading reaches the end.
Example: Safe File Reading
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
perror("Error opening file");
return 1;
}
int num;
while (fscanf(fp, "%d", &num) != EOF) {
printf("Read: %d\n", num);
}
fclose(fp);
6. Binary vs. Text Files
| Feature | Text Files ("r", "w") |
Binary Files ("rb", "wb") |
|---|---|---|
| Data Format | Human-readable (ASCII/Unicode) | Raw bytes (e.g., integers as 0x00000064) |
| Portability | Limited (line endings: \n vs. \r\n) |
High (exact byte representation) |
| Use Case | Logs, CSV data | Images, serialized objects, databases |
| Functions | fscanf(), fprintf() |
fread(), fwrite() |
Example: Binary File for NEPSE Stock Data
typedef struct { char symbol[10]; float price; } Stock;
Stock stocks[100];
FILE *fp = fopen("stocks.dat", "wb");
fwrite(stocks, sizeof(Stock), 100, fp); // Write 100 records at once
fclose(fp);
Visual: Binary File Structure
7. Practical Programs (Exam-Style)
Program 1: Copy File Contents
#include <stdio.h>
void copy_file(char *src, char *dest) {
FILE *fs = fopen(src, "r");
FILE *fd = fopen(dest, "w");
char ch;
if (fs == NULL || fd == NULL) {
printf("Error opening files!\n");
return;
}
while ((ch = fgetc(fs)) != EOF) {
fputc(ch, fd);
}
fclose(fs);
fclose(fd);
}
Trace:
| Step | fs (Source) |
fd (Destination) |
Action |
|---|---|---|---|
| 1 | "Hello" | (empty) | Open src.txt, dest.txt |
| 2 | "ello" | "H" | Copy 'H' |
| 3 | "llo" | "He" | Copy 'e' |
| ... | ... | ... | ... |
Program 2: Reverse a String to File
#include <stdio.h>
#include <string.h>
void reverse_to_file(char *input, char *output) {
FILE *fp = fopen(output, "w");
int len = strlen(input);
for (int i = len - 1; i >= 0; i--) {
fputc(input[i], fp);
}
fclose(fp);
}
Input: "TU" → Output File: "UT".
Visual:
Program 3: Odd/Even Number Separator
#include <stdio.h>
void separate_odd_even(int num) {
FILE *odd = fopen("Odd.dat", "a");
FILE *even = fopen("Even.dat", "a");
if (num % 2 == 0) {
fprintf(even, "%d\n", num);
} else {
fprintf(odd, "%d\n", num);
}
fclose(odd);
fclose(even);
}
Trace for Input 5:
| File | Before | After |
|---|---|---|
Odd.dat |
(empty) | 5 |
Even.dat |
(empty) | (unchanged) |
8. Common Pitfalls and Best Practices
- Forgetting to close files: Leaks resources. Always use
fclose(). - Assuming file existence: Use
fopen()checks oraccess()from<io.h>. - Buffer overflows: Use
fgets()instead ofgets()for strings. - Binary vs. text confusion: Use
"rb"/"wb"for non-text data (e.g., images). - Portability issues: Avoid hardcoding paths (e.g.,
"C:\\data\\file.txt"→"data/file.txt").
Exam Tip
- Memorize modes: Know when to use
"a"(append) vs."w"(overwrite). - Error handling: Always check
fopen()and loop conditions (e.g.,while (fscanf(...) != EOF)). - Binary files: Use
fread()/fwrite()with structs for efficiency (e.g., databases). - File pointers: Understand that
FILE *is a stream, not a direct file handle. - Practical questions: Expect programs like:
- Copying files.
- Reversing strings to files.
- Separating data into multiple files (odd/even, valid/invalid records).
- Real-world tie-ins: Relate to apps like eSewa (logs), Daraz (order management), or banks (transaction records).
Summary Table: Key Functions
| Task | Function | Example |
|---|---|---|
| Open file | fopen() |
FILE *fp = fopen("file.txt", "r"); |
| Close file | fclose() |
fclose(fp); |
| Read character | fgetc() |
ch = fgetc(fp); |
| Write character | fputc() |
fputc('A', fp); |
| Read formatted | fscanf() |
fscanf(fp, "%d", &num); |
| Write formatted | fprintf() |
fprintf(fp, "%s", str); |
| Read binary | fread() |
fread(&data, sizeof(data), 1, fp); |
| Write binary | fwrite() |
fwrite(&data, sizeof(data), 1, fp); |
| Check EOF | feof() |
while (!feof(fp)) |
| Seek position | fseek() |
fseek(fp, 100, SEEK_SET); |
Final Worked Example: Bank Transaction Log
Scenario: A bank writes transactions to transactions.log in append mode. Each entry includes:
- Timestamp
- Account ID
- Amount
- Type (deposit/withdrawal)
Code:
#include <stdio.h>
#include <time.h>
void log_transaction(char *type, int account_id, float amount) {
FILE *log = fopen("transactions.log", "a");
time_t t = time(NULL);
char *time_str = ctime(&t);
// Remove newline from ctime output
time_str[strlen(time_str) - 1] = '\0';
fprintf(log, "[%s] Account %d: %s Rs. %.2f\n",
time_str, account_id, type, amount);
fclose(log);
}
Output File (transactions.log):
[Mon Jun 10 14:30:00 2024] Account 1001: Deposit Rs. 5000.00
[Mon Jun 10 14:35:22 2024] Account 1001: Withdrawal Rs. 2000.00
Visual:
flowchart LR
A["User deposits Rs. 5000"] --> B["log_transaction(\"Deposit\", 1001, 5000)"]
B --> C["Append to transactions.log"]
C --> D["File grows with new entry"]Based on the TU BITM syllabus for C Programming (IT232), unit 10.
Discussion
Loading…