Elective Programming In C

Programming In CUnit 1114 min read

File Handling in C: Modes, Operations, and Structured Data Storage

Unit 11 of Programming In C covers file handling in C—how to create, read, write, and manipulate files using standard library functions (fopen, fclose, fprintf, fscanf, etc.), file opening modes, error handling, and integrating file operations with structures for real-world data storage (e.g., student records, employee

TAKEAWAYS:

  • File modes matter: Modes like "r", "w", "a", and "rb" determine how a file is opened (read-only, write-only, append, binary), and mixing them incorrectly causes runtime errors.
  • Structures + files = databases: Store structured data (e.g., student records) in files to persist beyond program execution, mimicking real-world systems like eSewa’s user data or bank transaction logs.
  • Error handling is critical: Always check if fopen() returns NULL and handle file operations gracefully to avoid crashes (e.g., when a file doesn’t exist).
  • Binary vs. text files: Binary mode ("wb", "rb") preserves exact data (e.g., images, serialized objects), while text mode ("w", "r") adds newline conversions—choose based on use case.
  • Sequential vs. random access: Sequential access (line-by-line) is simple but slow for large files; random access (fseek) enables direct jumps (e.g., updating a specific student record).
  • Real-world tie-ins: File handling powers apps like Khalti (transaction logs), Daraz (order databases), and NTC (bill records), where data must persist across sessions.

1. Why File Handling?

Programs often need to store data permanently (beyond runtime). Without files:

  • All data is lost when the program exits.
  • No way to share data between runs (e.g., a bank app can’t track accounts without saving them).

Example: When you log into eSewa, your transaction history isn’t recreated every time you open the app—it’s stored in a file (or database) on the server. Similarly, Ncell stores your call logs in files to bill you accurately.


2. File Opening Modes

Files in C are opened using fopen(), which takes two arguments:

  1. Filename (e.g., "students.txt").
  2. Mode (a string specifying how to open the file).
Mode Description Example Use Case
"r" Open for reading (file must exist). Displaying student records.
"w" Open for writing (creates/truncates file). Saving new employee data.
"a" Open for appending (adds to end of file). Logging transactions in Khalti.
"r+" Open for reading + writing (file must exist). Updating a Daraz order status.
"w+" Open for writing + reading (creates/truncates file). Editing a bank’s loan records.
"a+" Open for appending + reading (adds to end of file). Adding new NTC bill entries.
"rb" Open binary file for reading. Loading an image (e.g., profile pic in Pathao).
"wb" Open binary file for writing. Saving a serialized object (e.g., game save).

Visual: File Modes in Action

flowchart TD
    A["fopen(\"data.txt\", \"w\")"] -->|"Creates/Truncates"| B["File: Empty"]
    C["fopen(\"data.txt\", \"a\")"] -->|"Appends"| D["File: Old data + new"]
    E["fopen(\"data.txt\", \"r\")"] -->|"Reads"| F["File: Unchanged"]

Worked Example: Opening a File

#include <stdio.h>
int main() {
    FILE *fp = fopen("students.txt", "r"); // Open for reading
    if (fp == NULL) {
        printf("Error opening file!\n");
        return 1;
    }
    fclose(fp); // Always close the file
    return 0;
}

Trace:

Step Action File State
fopen() Opens "students.txt" in "r" File exists → OK
fp == NULL Checks for error fp points to file
fclose() Closes file File remains on disk

3. File Operations

Once a file is open, use these functions:

Function Purpose Example
fprintf() Write formatted data to file. fprintf(fp, "%s\n", name);
fscanf() Read formatted data from file. fscanf(fp, "%d", &rollno);
fgets() Read a line (including spaces) from file. fgets(buffer, 100, fp);
fputs() Write a string to file. fputs("Hello\n", fp);
fseek() Move file pointer to a specific position (bytes from start). fseek(fp, 100, SEEK_SET);
ftell() Return current position of file pointer. long pos = ftell(fp);
rewind() Reset file pointer to start. rewind(fp);

Visual: File Pointer Movement

flowchart LR
    A["Start"] -->|"fseek(fp, 50, SEEK_SET)"| B["Move to byte 50"]
    B -->|"fread()"| C["Read 10 bytes"]
    C -->|"ftell()"| D["Current pos: 60"]
    D -->|"rewind()"| A

Worked Example: Writing to a File

#include <stdio.h>
struct Student {
    char name[50];
    int rollno;
};
int main() {
    FILE *fp = fopen("students.txt", "w");
    struct Student s1 = {"Ramesh", 101};
    fprintf(fp, "%s %d\n", s1.name, s1.rollno); // Write to file
    fclose(fp);
    return 0;
}

File After Execution:

Ramesh 101

4. Storing Structured Data in Files

Problem: Past exam questions often ask to store records (e.g., students, employees) in files and retrieve specific entries. This mimics real-world systems like:

  • NTC: Storing bill records for each customer.
  • Banks: Saving account details for loan processing.
  • Daraz: Managing order statuses.

Step-by-Step: Storing and Retrieving Student Records

  1. Define a structure:
    struct Student {
        char name[50];
        int rollno;
        char college[50];
    };
    
  2. Write records to file:
    FILE *fp = fopen("students.dat", "wb"); // Binary mode for exact storage
    struct Student s1 = {"Sita", 201, "SoE"};
    fwrite(&s1, sizeof(struct Student), 1, fp); // Write one record
    fclose(fp);
    
  3. Read and filter records (e.g., find students from "SoE"):
    fp = fopen("students.dat", "rb");
    struct Student s;
    while (fread(&s, sizeof(struct Student), 1, fp) == 1) {
        if (strcmp(s.college, "SoE") == 0) {
            printf("%s %d\n", s.name, s.rollno); // Display matching records
        }
    }
    fclose(fp);
    

Visual: Binary File Storage

Trace for Filtering:

Step Action File Pointer Output
fopen("rb") Open binary file Start —
fread() (1st) Read Record 1 ("Sita") 0x007A —
strcmp("SoE") Match found 0x007A "Sita 201" printed
fread() (2nd) Read Record 2 ("Ram") EOF —
Loop ends EOF reached — —

5. Text vs. Binary Files: Key Differences

Feature Text Files ("r", "w") Binary Files ("rb", "wb")
Data Format Human-readable (ASCII/Unicode) Exact byte representation
Use Case Logs, CSV data Images, serialized objects
Speed Slower (conversions) Faster (direct memory access)
Portability Limited (line endings vary) High (platform-independent)
Example students.txt (CSV) profile.png (image)

Real-World Example:

  • Khalti uses binary files/databases to store transaction hashes (exact byte storage for security).
  • Daraz uses text files for order logs (human-readable for audits).

6. Error Handling in File Operations

Always check for errors when opening files:

FILE *fp = fopen("nonexistent.txt", "r");
if (fp == NULL) {
    perror("Error"); // Prints: "Error: No such file or directory"
    return 1;
}

Common Errors:

  • NULL pointer: File not found or permission denied.
  • fprintf()/fscanf() failure: Disk full or corrupted file.

Worked Example: Safe File Writing

FILE *fp = fopen("backup.dat", "wb");
if (fp == NULL) {
    printf("Backup failed!\n");
    exit(1);
}
int data = 42;
if (fwrite(&data, sizeof(int), 1, fp) != 1) {
    printf("Write error!\n");
}
fclose(fp);

7. Random Access vs. Sequential Access

Method Description Example Use Case
Sequential Read/write line-by-line (slow for large files). Reading a log file (e.g., NTC bills).
Random Jump to any position using fseek() (fast for large files). Updating a specific student record.

Worked Example: Random Access

FILE *fp = fopen("students.dat", "rb");
struct Student s;
fseek(fp, 2 * sizeof(struct Student), SEEK_SET); // Jump to 3rd record
fread(&s, sizeof(struct Student), 1, fp);
printf("Record 3: %s %d\n", s.name, s.rollno);
fclose(fp);

Visual: Random Access


8. Integrating Structures and Files (Exam Focus)

Past Exam Question Analysis:

"Create a structure called student with name, rollno, and college for 10 students. Display the name of students who study at SoE."

Solution Code:

#include <stdio.h>
#include <string.h>
struct Student {
    char name[50];
    int rollno;
    char college[50];
};
int main() {
    struct Student students[10];
    FILE *fp = fopen("students.txt", "w");
    for (int i = 0; i < 10; i++) {
        printf("Enter name, rollno, college: ");
        scanf("%s %d %s", students[i].name, &students[i].rollno, students[i].college);
        fprintf(fp, "%s %d %s\n", students[i].name, students[i].rollno, students[i].college);
    }
    fclose(fp);

    // Read and filter
    fp = fopen("students.txt", "r");
    while (fscanf(fp, "%s %d %s", students[0].name, &students[0].rollno, students[0].college) != EOF) {
        if (strcmp(students[0].college, "SoE") == 0) {
            printf("SoE Student: %s %d\n", students[0].name, students[0].rollno);
        }
    }
    fclose(fp);
    return 0;
}

Visual: File After Input

Ramesh 101 SoE
Sita 102 SoCS
Hari 103 SoE
...

In the Real World

  1. eSewa/Khalti Transactions:

    • Idea Used: File handling (or databases) to store transaction logs.
    • How: Every payment is written to a file (or database) with details like user_id, amount, timestamp. When you check your history, the app reads from this file.
    • Code Analogy:
      // Pseudocode for Khalti's transaction log
      FILE *fp = fopen("transactions.dat", "a");
      fprintf(fp, "%s %d %.2f\n", user_id, amount, timestamp);
      fclose(fp);
      
  2. Daraz Order Management:

    • Idea Used: Binary files for storing order statuses (e.g., "Processing", "Shipped").
    • How: Each order is a record in a binary file. When an order is updated (e.g., "Shipped"), fseek() jumps to the order’s position and rewrites its status.
    • Real Scenario: If you track an order on Daraz, the system reads your order ID, uses fseek() to locate it, and displays the latest status.
  3. NTC Bill Generation:

    • Idea Used: Sequential file reading to calculate bills.
    • How: NTC stores consumption data for each customer in a text file. When generating a bill, it reads the file line-by-line (fscanf), multiplies usage by rates, and writes the total to a new file.
    • Worked Example:
      // Pseudocode for NTC bill calculation
      FILE *fp = fopen("consumption.txt", "r");
      float units;
      while (fscanf(fp, "%f", &units) != EOF) {
          float bill = units * 5.0; // Rs. 5 per unit
          printf("Bill: Rs. %.2f\n", bill);
      }
      fclose(fp);
      

Exam Tip

  1. File Modes Are Tricky:

    • "w" truncates the file; "a" appends. Mixing them up is a common mistake.
    • Exam Pitfall: Forgetting to check if fopen() returns NULL (loses marks).
  2. Structures + Files = Full Marks:

    • Always define a structure first, then use fprintf/fscanf or fread/fwrite.
    • Pro Tip: For binary files, use sizeof(struct) to ensure correct byte counts.
  3. Filtering Data:

    • Questions often ask to display records matching a condition (e.g., college == "SoE").
    • Use while(fread(...) != EOF) or while(fscanf(...) != EOF) in loops.
  4. Binary vs. Text:

    • Binary ("wb") is faster and exact; text ("w") is human-readable but slower.
    • Exam Clue: If the question mentions "exact storage," use binary mode.
  5. Error Handling:

    • Always include checks for NULL after fopen() and verify read/write operations.
    • Sample Answer Snippet:
      if ((fp = fopen("data.txt", "r")) == NULL) {
          printf("Error: File not found.\n");
      }
      
  6. Past Exam Patterns:

    • Part (a): Implement file operations with structures (e.g., store 10 records, filter).
    • Part (b): Explain file modes or compare text/binary files (theory + table).
    • Short Notes: Focus on fopen() modes, fread/fwrite, and error handling.

Quick Revision Table

Concept Key Points Example
File Modes "r", "w", "a", "rb", "wb" fopen("file.txt", "a")
Structures in Files Use fprintf/fscanf for text, fread/fwrite for binary. Store struct Student records.
Error Handling Check fopen() return value and read/write status. if (fp == NULL) { ... }
Random Access fseek(fp, offset, SEEK_SET) to jump to a record. Update a specific student.
Binary Files Faster, exact storage (e.g., images, serialized data). fwrite(&data, sizeof(data), 1, fp);

Based on the PU BE Computer (PU) syllabus for Programming In C, unit 11.

Discussion

Loading…