CACS151 C Programming

C ProgrammingUnit 109 min read

File Handling in C: Modes, Text vs Binary, Operations & Real-World Applications

Unit 10 of C Programming covers file handling fundamentals—text vs binary files, opening modes (read/write/append), file operations (open/close/read/write), error handling, and practical applications like data storage and processing. Learn with visual traces, real-world examples (e.g., eSewa transaction logs), and exam


Core Concepts: Files in C

1. What is a File?

A file is a named collection of related data stored on secondary memory (e.g., hard disk, USB). Files persist even after the program terminates, unlike variables stored in RAM.

Why use files?

  • Persistence: Save data for later use (e.g., user accounts, transaction history).
  • Efficiency: Faster access than user input/output for large datasets.
  • Sharing: Multiple programs can read/write the same file (e.g., student.txt for a university system).

2. Types of Files

A. Text Files vs. Binary Files

Feature Text File Binary File
Data Format ASCII/Unicode (human-readable) Raw bytes (machine-readable)
Storage Efficiency Less efficient (extra bytes for formatting) Highly efficient (no overhead)
Speed Slower (conversion to/from text) Faster (direct memory access)
Use Cases Logs, configs, CSV data Images, executables, databases (e.g., SQLite)
Example in Nepal eSewa_transaction_log.txt Ncell_customer_data.bin
[object Object]0[object Object]1
Text (ASCII) vs Binary (UTF-8 emoji) byte representation

Visual: Text vs. Binary File Structure


In the Real World

  1. eSewa Transaction Logs

    • Idea Used: Text files (eSewa_transactions.txt) store every payment record (user ID, amount, timestamp) in ASCII format.
    • Why? Human-readable for audits; simple to parse for generating receipts.
    • Code Tie-In: Later, you’ll write a program to filter transactions by date (using fscanf and fprintf).
  2. Ncell Customer Database

    • Idea Used: Binary files (customer_data.bin) store SIM records (phone number, balance, usage history) as raw bytes.
    • Why? Faster access for real-time balance checks; compact storage for millions of records.
  3. Daraz Order Queue

    • Idea Used: Temporary text files (pending_orders.txt) manage unfulfilled orders. The system reads/writes to this file when orders are placed or shipped.
    • Worked Example: Simulate Daraz’s order processing:
      // Write an order to pending_orders.txt
      FILE *fp = fopen("pending_orders.txt", "a");
      fprintf(fp, "OrderID: %d, User: %s, Status: Pending\n", 101, "user123");
      fclose(fp);
      
      Trace:
      Step File Content (pending_orders.txt)
      Initial (empty)
      After Step OrderID: 101, User: user123, Status: Pending

3. File Opening Modes

C uses fopen() to open files with specific modes. Memorize these 6 modes:

Mode Meaning Example Use Case
"r" Read-only (file must exist) Reading student.txt
"w" Write-only (creates/truncates file) Creating new_log.txt
"a" Append-only (creates file if missing) Adding to eSewa_transactions.txt
"r+" Read+write (file must exist) Updating config.ini
"w+" Read+write (creates/truncates file) Replacing backup.db
"a+" Read+append (creates file if missing) Logging errors to error_log.txt
"b" (add) Binary mode (e.g., "rb", "wb") Handling image.bin

Visual: File Modes in Action

flowchart TD
    A["fopen(\"data.txt\", \"w\")"] -->|"Truncates"| B["Empty File"]
    A --> C["Creates if missing"]
    D["fopen(\"data.txt\", \"a\")"] -->|"Appends"| E["Existing Content\nNew Data"]
    F["fopen(\"data.txt\", \"r+\")"] -->|"Read/Write"| G["Existing Content\nModified"]

4. File Operations

A. Opening and Closing Files

#include <stdio.h>
int main() {
    FILE *fp;
    fp = fopen("example.txt", "r");  // Open for reading
    if (fp == NULL) {
        printf("Error opening file!");
        return 1;
    }
    // File operations here...
    fclose(fp);  // Always close to free resources
    return 0;
}

Trace:

Variable Step 1 (fopen) Step 2 (Operations) Step 3 (fclose)
fp 0x7ff... (valid) Same NULL

B. Reading/Writing Data

1. Character-by-Character (fgetc, fputc)

char ch;
ch = fgetc(fp);  // Reads 1 character
fputc('A', fp);  // Writes 1 character

2. Line-by-Line (fgets, fputs)

char line[100];
fgets(line, 100, fp);  // Reads a line (including newline)
fputs("Hello\n", fp);  // Writes a line

3. Formatted I/O (fscanf, fprintf)

int id;
char name[50];
fscanf(fp, "%d %s", &id, name);  // Reads formatted data
fprintf(fp, "%d %s", 101, "Alice"); // Writes formatted data

Visual: Reading a Student Record


C. Binary File Operations

For binary files, use:

  • fread() / fwrite() for raw bytes.
  • No formatting (e.g., no %d for integers).

Example: Storing a Struct in Binary

typedef struct {
    int id;
    char name[50];
} Student;

Student s = {101, "Alice"};
FILE *fp = fopen("students.bin", "wb");
fwrite(&s, sizeof(Student), 1, fp);  // Write binary
fclose(fp);

Trace:

Step File (students.bin)
After fwrite Raw bytes: 64 00 00 00 01 00 00 00 A A l i c e...

5. Error Handling

Always check if fopen() returns NULL:

FILE *fp = fopen("nonexistent.txt", "r");
if (fp == NULL) {
    perror("Error");  // Prints system error (e.g., "No such file")
    return 1;
}

Common Errors:

  • ENOENT: File does not exist (use "a" mode to create it).
  • EACCES: Permission denied (check file permissions).

6. Practical Example: Filtering Prime Numbers

Problem: Given numbers.txt with integers, write a program to extract primes into primes.txt.

Filter primesRenamestudent.txttemp.txtoutput.txt
File operations workflow for prime number filtering

Solution:

#include <stdio.h>
#include <stdbool.h>

bool isPrime(int n) {
    if (n <= 1) return false;
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) return false;
    }
    return true;
}

int main() {
    FILE *in = fopen("numbers.txt", "r");
    FILE *out = fopen("primes.txt", "w");
    int num;

    while (fscanf(in, "%d", &num) == 1) {
        if (isPrime(num)) {
            fprintf(out, "%d ", num);
        }
    }
    fclose(in);
    fclose(out);
    return 0;
}

Trace:

File Initial Content After Processing
numbers.txt 4 7 10 13 17 (unchanged)
primes.txt (empty) 7 13 17

Real-World Tie-In:

  • NEPSE Stock Data: Imagine stock_prices.txt contains daily closing prices. Your program could filter and save only days when the price was above a threshold (e.g., >2000).

7. Common Pitfalls & Best Practices

Pitfall Solution
Forgetting fclose() Always close files to avoid memory leaks.
Not checking fopen() return Use if (fp == NULL) to handle errors.
Mixing text/binary modes Specify "b" (e.g., "rb") for binary.
Buffer overflows in fgets Pass buffer size (e.g., fgets(buf, 100, fp)).
Not flushing buffers (fflush) Use fflush(fp) before critical writes.

Exam Tip

  1. Define Modes Clearly: In exams, list all 6 modes with examples (e.g., "w" truncates, "a" appends).
  2. Code Structure:
    • Always include #include <stdio.h>.
    • Check fopen() return value.
    • Close files with fclose().
  3. Common Questions:
    • Copy a file: Use fgetc/fputc in a loop.
    • Delete a record: Read all lines except the target, rewrite the file.
    • Binary vs. text: Compare storage, speed, and use cases (see table above).
  4. Trace Tables: For programs like prime filtering, show the state of files before and after processing.

Example Answer Snippet (for "delete a record"):

// Delete record with ID=101 from student.txt
FILE *temp = fopen("temp.txt", "w");
FILE *in = fopen("student.txt", "r");
int id; char name[50];

while (fscanf(in, "%d %s", &id, name) == 2) {
    if (id != 101) {  // Skip record to delete
        fprintf(temp, "%d %s\n", id, name);
    }
}
fclose(in); fclose(temp);
remove("student.txt"); rename("temp.txt", "student.txt");

Based on the TU BCA syllabus for C Programming (CACS151), unit 10.

Discussion

Loading…