File IO Operations

Introduction

File Input/Output (I/O) operations in C allow programs to read data from files and write data to files, enabling persistent data storage and retrieval. C provides a comprehensive set of functions for file handling, including opening, closing, reading, writing, and manipulating files. Understanding file I/O is essential for creating programs that can store and process large amounts of data.

Key Concepts

File Pointer: Variable that points to a file structure File Modes: Specifications for how a file should be opened Stream: Sequence of bytes flowing to/from a file Buffer: Temporary storage area for file data EOF: End-of-file marker indicating file termination

Basic File Operations

Opening and Closing Files

#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE *filePtr;
    
    // Open file for writing
    filePtr = fopen("sample.txt", "w");
    if (filePtr == NULL) {
        printf("Error: Cannot open file for writing!\n");
        return 1;
    }
    
    printf("File opened successfully for writing.\n");
    
    // Write some data
    fprintf(filePtr, "Hello, File I/O!\n");
    fprintf(filePtr, "This is line 2.\n");
    fprintf(filePtr, "Line 3 with number: %d\n", 42);
    
    // Close the file
    fclose(filePtr);
    printf("File closed after writing.\n");
    
    // Open file for reading
    filePtr = fopen("sample.txt", "r");
    if (filePtr == NULL) {
        printf("Error: Cannot open file for reading!\n");
        return 1;
    }
    
    printf("\nFile contents:\n");
    char buffer[100];
    
    // Read and display file contents
    while (fgets(buffer, sizeof(buffer), filePtr) != NULL) {
        printf("%s", buffer);
    }
    
    fclose(filePtr);
    printf("\nFile closed after reading.\n");
    
    return 0;
}

File Mode Examples

#include <stdio.h>
#include <string.h>

void demonstrateFileModes() {
    FILE *file;
    char data[] = "Sample data for demonstration";
    char readBuffer[100];
    
    // Write mode - creates new file or overwrites existing
    printf("1. Write Mode ('w'):\n");
    file = fopen("demo_write.txt", "w");
    if (file != NULL) {
        fprintf(file, "Original content\n");
        fclose(file);
        printf("   Written: 'Original content'\n");
    }
    
    // Append mode - adds to end of existing file
    printf("2. Append Mode ('a'):\n");
    file = fopen("demo_write.txt", "a");
    if (file != NULL) {
        fprintf(file, "Appended content\n");
        fclose(file);
        printf("   Appended: 'Appended content'\n");
    }
    
    // Read mode - reads existing file
    printf("3. Read Mode ('r'):\n");
    file = fopen("demo_write.txt", "r");
    if (file != NULL) {
        printf("   File contents:\n");
        while (fgets(readBuffer, sizeof(readBuffer), file) != NULL) {
            printf("   %s", readBuffer);
        }
        fclose(file);
    }
    
    // Read/Write mode - opens existing file for both operations
    printf("4. Read/Write Mode ('r+'):\n");
    file = fopen("demo_write.txt", "r+");
    if (file != NULL) {
        fseek(file, 0, SEEK_END); // Go to end of file
        fprintf(file, "Added via r+ mode\n");
        
        fseek(file, 0, SEEK_SET); // Go to beginning
        printf("   Updated file contents:\n");
        while (fgets(readBuffer, sizeof(readBuffer), file) != NULL) {
            printf("   %s", readBuffer);
        }
        fclose(file);
    }
}

int main() {
    demonstrateFileModes();
    return 0;
}

Character-based I/O

Reading and Writing Characters

#include <stdio.h>

void characterIOExample() {
    FILE *file;
    char ch;
    
    // Write characters to file
    file = fopen("chars.txt", "w");
    if (file == NULL) {
        printf("Error opening file for writing!\n");
        return;
    }
    
    printf("Writing characters A-Z to file...\n");
    for (ch = 'A'; ch <= 'Z'; ch++) {
        fputc(ch, file);
        if ((ch - 'A' + 1) % 5 == 0) {
            fputc('\n', file); // New line every 5 characters
        }
    }
    fclose(file);
    
    // Read characters from file
    file = fopen("chars.txt", "r");
    if (file == NULL) {
        printf("Error opening file for reading!\n");
        return;
    }
    
    printf("Reading characters from file:\n");
    while ((ch = fgetc(file)) != EOF) {
        printf("%c", ch);
    }
    printf("\n");
    
    fclose(file);
}

void interactiveCharacterInput() {
    FILE *file;
    char ch;
    
    file = fopen("user_input.txt", "w");
    if (file == NULL) {
        printf("Error creating file!\n");
        return;
    }
    
    printf("Enter text (press Ctrl+Z then Enter to stop):\n");
    while ((ch = getchar()) != EOF) {
        fputc(ch, file);
    }
    
    fclose(file);
    printf("Input saved to user_input.txt\n");
}

int main() {
    characterIOExample();
    printf("\n");
    interactiveCharacterInput();
    
    return 0;
}

String-based I/O

Reading and Writing Strings

#include <stdio.h>
#include <string.h>

void stringIOExample() {
    FILE *file;
    char names[][30] = {
        "Alice Johnson",
        "Bob Smith", 
        "Charlie Brown",
        "Diana Wilson",
        "Eve Davis"
    };
    char readBuffer[50];
    
    // Write strings to file
    file = fopen("names.txt", "w");
    if (file == NULL) {
        printf("Error opening file for writing!\n");
        return;
    }
    
    printf("Writing names to file:\n");
    for (int i = 0; i < 5; i++) {
        fputs(names[i], file);
        fputs("\n", file);
        printf("Written: %s\n", names[i]);
    }
    fclose(file);
    
    // Read strings from file
    file = fopen("names.txt", "r");
    if (file == NULL) {
        printf("Error opening file for reading!\n");
        return;
    }
    
    printf("\nReading names from file:\n");
    int lineNumber = 1;
    while (fgets(readBuffer, sizeof(readBuffer), file) != NULL) {
        // Remove newline character if present
        readBuffer[strcspn(readBuffer, "\n")] = '\0';
        printf("Line %d: %s\n", lineNumber++, readBuffer);
    }
    
    fclose(file);
}

void processTextFile() {
    FILE *input, *output;
    char line[100];
    int lineCount = 0, wordCount = 0, charCount = 0;
    
    // Create input file with sample text
    input = fopen("sample_text.txt", "w");
    if (input != NULL) {
        fprintf(input, "This is a sample text file.\n");
        fprintf(input, "It contains multiple lines.\n");
        fprintf(input, "We will process this file.\n");
        fprintf(input, "And count lines, words, and characters.\n");
        fclose(input);
    }
    
    // Process the file
    input = fopen("sample_text.txt", "r");
    output = fopen("statistics.txt", "w");
    
    if (input == NULL || output == NULL) {
        printf("Error opening files!\n");
        return;
    }
    
    fprintf(output, "Text File Analysis Report\n");
    fprintf(output, "========================\n\n");
    
    while (fgets(line, sizeof(line), input) != NULL) {
        lineCount++;
        charCount += strlen(line);
        
        // Count words in this line
        char *word = strtok(line, " \t\n");
        while (word != NULL) {
            wordCount++;
            word = strtok(NULL, " \t\n");
        }
        
        fprintf(output, "Line %d: %d characters\n", lineCount, (int)strlen(line));
    }
    
    fprintf(output, "\nSummary:\n");
    fprintf(output, "Total Lines: %d\n", lineCount);
    fprintf(output, "Total Words: %d\n", wordCount);
    fprintf(output, "Total Characters: %d\n", charCount);
    
    fclose(input);
    fclose(output);
    
    printf("Text analysis complete. Results saved to statistics.txt\n");
}

int main() {
    stringIOExample();
    printf("\n");
    processTextFile();
    
    return 0;
}

Formatted I/O

Using fprintf and fscanf

#include <stdio.h>

struct Student {
    int rollNo;
    char name[30];
    float marks;
    char grade;
};

void writeStudentData() {
    FILE *file;
    struct Student students[] = {
        {101, "Alice Johnson", 85.5, 'A'},
        {102, "Bob Smith", 78.0, 'B'},
        {103, "Charlie Brown", 92.5, 'A'},
        {104, "Diana Wilson", 88.0, 'B'},
        {105, "Eve Davis", 76.5, 'C'}
    };
    
    file = fopen("students.dat", "w");
    if (file == NULL) {
        printf("Error creating student file!\n");
        return;
    }
    
    // Write header
    fprintf(file, "Student Database\n");
    fprintf(file, "================\n");
    fprintf(file, "Roll No\tName\t\tMarks\tGrade\n");
    fprintf(file, "-------\t----\t\t-----\t-----\n");
    
    // Write student data
    for (int i = 0; i < 5; i++) {
        fprintf(file, "%d\t%s\t%.1f\t%c\n",
                students[i].rollNo,
                students[i].name,
                students[i].marks,
                students[i].grade);
    }
    
    fclose(file);
    printf("Student data written to students.dat\n");
}

void readStudentData() {
    FILE *file;
    char buffer[100];
    int rollNo;
    char name[30];
    float marks;
    char grade;
    
    file = fopen("students.dat", "r");
    if (file == NULL) {
        printf("Error opening student file!\n");
        return;
    }
    
    // Skip header lines
    for (int i = 0; i < 4; i++) {
        fgets(buffer, sizeof(buffer), file);
    }
    
    printf("Reading student data:\n");
    printf("Roll No\tName\t\tMarks\tGrade\n");
    printf("-------\t----\t\t-----\t-----\n");
    
    // Read student records
    while (fscanf(file, "%d\t%s\t%f\t%c", &rollNo, name, &marks, &grade) == 4) {
        printf("%d\t%-15s\t%.1f\t%c\n", rollNo, name, marks, grade);
    }
    
    fclose(file);
}

void processInventoryData() {
    FILE *file;
    int productId, quantity;
    char productName[25];
    float price;
    float totalValue = 0;
    int itemCount = 0;
    
    // Create inventory file
    file = fopen("inventory.csv", "w");
    if (file != NULL) {
        fprintf(file, "ID,Name,Price,Quantity\n");
        fprintf(file, "1001,Laptop,999.99,10\n");
        fprintf(file, "1002,Mouse,29.99,50\n");
        fprintf(file, "1003,Keyboard,79.99,30\n");
        fprintf(file, "1004,Monitor,299.99,15\n");
        fclose(file);
    }
    
    // Process inventory file
    file = fopen("inventory.csv", "r");
    if (file == NULL) {
        printf("Error opening inventory file!\n");
        return;
    }
    
    // Skip header
    char header[100];
    fgets(header, sizeof(header), file);
    
    printf("Inventory Report:\n");
    printf("ID\tName\t\tPrice\tQty\tValue\n");
    printf("----\t----\t\t-----\t---\t-----\n");
    
    while (fscanf(file, "%d,%24[^,],%f,%d", &productId, productName, &price, &quantity) == 4) {
        float itemValue = price * quantity;
        totalValue += itemValue;
        itemCount++;
        
        printf("%d\t%-12s\t$%.2f\t%d\t$%.2f\n",
               productId, productName, price, quantity, itemValue);
    }
    
    printf("\nSummary: %d items, Total Value: $%.2f\n", itemCount, totalValue);
    
    fclose(file);
}

int main() {
    writeStudentData();
    readStudentData();
    printf("\n");
    processInventoryData();
    
    return 0;
}

Binary File Operations

Reading and Writing Binary Data

#include <stdio.h>
#include <string.h>

struct Employee {
    int empId;
    char name[30];
    float salary;
    int age;
};

void writeBinaryData() {
    FILE *file;
    struct Employee employees[] = {
        {1001, "John Doe", 55000.0, 28},
        {1002, "Jane Smith", 62000.0, 32},
        {1003, "Bob Johnson", 48000.0, 25},
        {1004, "Alice Brown", 71000.0, 35}
    };
    
    file = fopen("employees.bin", "wb");
    if (file == NULL) {
        printf("Error creating binary file!\n");
        return;
    }
    
    // Write number of records first
    int count = 4;
    fwrite(&count, sizeof(int), 1, file);
    
    // Write employee records
    fwrite(employees, sizeof(struct Employee), count, file);
    
    fclose(file);
    printf("Binary data written to employees.bin\n");
    printf("File size: %d bytes\n", (int)(sizeof(int) + count * sizeof(struct Employee)));
}

void readBinaryData() {
    FILE *file;
    struct Employee emp;
    int count;
    
    file = fopen("employees.bin", "rb");
    if (file == NULL) {
        printf("Error opening binary file!\n");
        return;
    }
    
    // Read number of records
    fread(&count, sizeof(int), 1, file);
    
    printf("Reading %d employee records from binary file:\n", count);
    printf("ID\tName\t\tSalary\t\tAge\n");
    printf("----\t----\t\t------\t\t---\n");
    
    // Read and display each record
    for (int i = 0; i < count; i++) {
        fread(&emp, sizeof(struct Employee), 1, file);
        printf("%d\t%-15s\t$%.2f\t\t%d\n",
               emp.empId, emp.name, emp.salary, emp.age);
    }
    
    fclose(file);
}

void compareFilesSizes() {
    FILE *textFile, *binaryFile;
    struct Employee emp = {1001, "Sample Employee", 50000.0, 30};
    
    // Write to text file
    textFile = fopen("emp_text.txt", "w");
    if (textFile != NULL) {
        fprintf(textFile, "%d %s %.2f %d\n", emp.empId, emp.name, emp.salary, emp.age);
        fclose(textFile);
    }
    
    // Write to binary file
    binaryFile = fopen("emp_binary.bin", "wb");
    if (binaryFile != NULL) {
        fwrite(&emp, sizeof(struct Employee), 1, binaryFile);
        fclose(binaryFile);
    }
    
    // Compare file sizes
    textFile = fopen("emp_text.txt", "r");
    binaryFile = fopen("emp_binary.bin", "rb");
    
    if (textFile != NULL && binaryFile != NULL) {
        fseek(textFile, 0, SEEK_END);
        long textSize = ftell(textFile);
        
        fseek(binaryFile, 0, SEEK_END);
        long binarySize = ftell(binaryFile);
        
        printf("\nFile Size Comparison:\n");
        printf("Text file: %ld bytes\n", textSize);
        printf("Binary file: %ld bytes\n", binarySize);
        printf("Space saved: %ld bytes (%.1f%%)\n", 
               textSize - binarySize, 
               ((float)(textSize - binarySize) / textSize) * 100);
        
        fclose(textFile);
        fclose(binaryFile);
    }
}

int main() {
    writeBinaryData();
    readBinaryData();
    compareFilesSizes();
    
    return 0;
}

File Position and Seeking

File Navigation Functions

#include <stdio.h>
#include <string.h>

void demonstrateFilePositioning() {
    FILE *file;
    char data[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    char buffer[10];
    
    // Create file with alphabet
    file = fopen("alphabet.txt", "w");
    if (file != NULL) {
        fputs(data, file);
        fclose(file);
    }
    
    // Demonstrate file positioning
    file = fopen("alphabet.txt", "r");
    if (file == NULL) {
        printf("Error opening file!\n");
        return;
    }
    
    printf("File positioning demonstration:\n");
    
    // Read from beginning
    printf("1. Reading from beginning (first 5 chars): ");
    fread(buffer, 1, 5, file);
    buffer[5] = '\0';
    printf("%s\n", buffer);
    
    // Get current position
    long pos = ftell(file);
    printf("   Current position: %ld\n", pos);
    
    // Seek to position 10
    fseek(file, 10, SEEK_SET);
    printf("2. After seeking to position 10: ");
    fread(buffer, 1, 5, file);
    buffer[5] = '\0';
    printf("%s\n", buffer);
    
    // Seek relative to current position
    fseek(file, 3, SEEK_CUR);
    printf("3. After seeking +3 from current: ");
    fread(buffer, 1, 3, file);
    buffer[3] = '\0';
    printf("%s\n", buffer);
    
    // Seek from end
    fseek(file, -5, SEEK_END);
    printf("4. Last 5 characters: ");
    fread(buffer, 1, 5, file);
    buffer[5] = '\0';
    printf("%s\n", buffer);
    
    // Reset to beginning
    rewind(file);
    printf("5. After rewind: ");
    fread(buffer, 1, 3, file);
    buffer[3] = '\0';
    printf("%s\n", buffer);
    
    fclose(file);
}

void randomAccessExample() {
    FILE *file;
    int numbers[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
    int value, index;
    
    // Write numbers to binary file
    file = fopen("numbers.bin", "wb");
    if (file != NULL) {
        fwrite(numbers, sizeof(int), 10, file);
        fclose(file);
        printf("Written 10 numbers to binary file\n");
    }
    
    // Random access reading
    file = fopen("numbers.bin", "rb");
    if (file == NULL) {
        printf("Error opening numbers file!\n");
        return;
    }
    
    printf("\nRandom access reading:\n");
    int indices[] = {7, 2, 9, 0, 5};
    
    for (int i = 0; i < 5; i++) {
        index = indices[i];
        fseek(file, index * sizeof(int), SEEK_SET);
        fread(&value, sizeof(int), 1, file);
        printf("Index %d: %d\n", index, value);
    }
    
    fclose(file);
}

int main() {
    demonstrateFilePositioning();
    printf("\n");
    randomAccessExample();
    
    return 0;
}

Error Handling and File Status

Comprehensive Error Checking

#include <stdio.h>
#include <errno.h>
#include <string.h>

void robustFileOperations() {
    FILE *file;
    char filename[] = "test_file.txt";
    char data[] = "Test data for error handling demonstration";
    char buffer[100];
    
    printf("Robust file operations demonstration:\n");
    
    // Safe file opening with error checking
    file = fopen(filename, "w");
    if (file == NULL) {
        printf("Error opening %s for writing: %s\n", filename, strerror(errno));
        return;
    }
    printf("1. File opened successfully for writing\n");
    
    // Write with error checking
    if (fputs(data, file) == EOF) {
        printf("Error writing to file: %s\n", strerror(errno));
        fclose(file);
        return;
    }
    printf("2. Data written successfully\n");
    
    // Check for write errors
    if (ferror(file)) {
        printf("Write error detected!\n");
        clearerr(file);
    }
    
    fclose(file);
    
    // Open for reading
    file = fopen(filename, "r");
    if (file == NULL) {
        printf("Error opening %s for reading: %s\n", filename, strerror(errno));
        return;
    }
    
    // Read with error checking
    if (fgets(buffer, sizeof(buffer), file) == NULL) {
        if (feof(file)) {
            printf("End of file reached\n");
        } else if (ferror(file)) {
            printf("Read error: %s\n", strerror(errno));
        }
    } else {
        printf("3. Read successfully: %s\n", buffer);
    }
    
    // Check file status
    printf("4. File status:\n");
    printf("   EOF indicator: %s\n", feof(file) ? "Yes" : "No");
    printf("   Error indicator: %s\n", ferror(file) ? "Yes" : "No");
    printf("   Current position: %ld\n", ftell(file));
    
    fclose(file);
    
    // Attempt to open non-existent file
    printf("5. Attempting to open non-existent file:\n");
    file = fopen("nonexistent.txt", "r");
    if (file == NULL) {
        printf("   Expected error: %s\n", strerror(errno));
    } else {
        fclose(file);
    }
}

void fileAccessPermissions() {
    FILE *file;
    
    printf("\nFile access permissions test:\n");
    
    // Try different access modes
    const char *modes[] = {"r", "w", "a", "r+", "w+", "a+"};
    const char *descriptions[] = {
        "Read only",
        "Write only (overwrite)",
        "Append only",
        "Read/Write (existing file)",
        "Read/Write (overwrite)",
        "Read/Append"
    };
    
    for (int i = 0; i < 6; i++) {
        printf("%d. %s mode ('%s'): ", i+1, descriptions[i], modes[i]);
        
        file = fopen("access_test.txt", modes[i]);
        if (file != NULL) {
            printf("Success\n");
            
            // Test write capability
            if (strchr(modes[i], 'w') || strchr(modes[i], 'a') || strchr(modes[i], '+')) {
                fprintf(file, "Test write in %s mode\n", modes[i]);
            }
            
            fclose(file);
        } else {
            printf("Failed - %s\n", strerror(errno));
        }
    }
}

int main() {
    robustFileOperations();
    fileAccessPermissions();
    
    return 0;
}

Practical File Applications

Log File Management

#include <stdio.h>
#include <time.h>
#include <string.h>

void writeLogEntry(const char *level, const char *message) {
    FILE *logFile;
    time_t now;
    char timeStr[26];
    
    // Get current time
    time(&now);
    strcpy(timeStr, ctime(&now));
    timeStr[strlen(timeStr) - 1] = '\0'; // Remove newline
    
    // Open log file in append mode
    logFile = fopen("application.log", "a");
    if (logFile == NULL) {
        printf("Error: Cannot write to log file\n");
        return;
    }
    
    // Write log entry
    fprintf(logFile, "[%s] %s: %s\n", timeStr, level, message);
    fclose(logFile);
}

void demonstrateLogging() {
    printf("Logging demonstration:\n");
    
    writeLogEntry("INFO", "Application started");
    writeLogEntry("DEBUG", "Loading configuration file");
    writeLogEntry("INFO", "User logged in");
    writeLogEntry("WARNING", "Low disk space detected");
    writeLogEntry("ERROR", "Database connection failed");
    writeLogEntry("INFO", "Application terminated");
    
    printf("Log entries written to application.log\n");
    
    // Read and display log file
    FILE *logFile = fopen("application.log", "r");
    if (logFile != NULL) {
        printf("\nLog file contents:\n");
        char line[200];
        while (fgets(line, sizeof(line), logFile) != NULL) {
            printf("%s", line);
        }
        fclose(logFile);
    }
}

int main() {
    demonstrateLogging();
    return 0;
}

Best Practices

  1. Always check file operations for success/failure
  2. Close files after operations to free resources
  3. Use appropriate file modes for your needs
  4. Handle errors gracefully with meaningful messages
  5. Use binary mode for non-text data
  6. Validate file paths before opening
  7. Use buffered I/O for better performance

Summary

File I/O operations in C provide comprehensive capabilities for data persistence and manipulation. Understanding file modes, proper error handling, and the various I/O functions (character, string, formatted, and binary) is essential for building robust applications. Proper file management, including opening, reading, writing, positioning, and closing files, ensures data integrity and efficient resource usage.


Part of BCA Programming with C Course (UGCOA22J201)