File Access Modes

Introduction

File access modes in C specify how a file should be opened and what operations can be performed on it. When opening a file using fopen(), you must specify the appropriate mode string that determines whether the file is opened for reading, writing, appending, or a combination of these operations.

Key Concepts

Access Mode: String specifying how file should be opened Read Mode: Opens file for input operations only Write Mode: Opens file for output operations, creates new or overwrites Append Mode: Opens file for writing at the end Binary Mode: Handles file as binary data without translation Text Mode: Default mode with possible line ending translation

Basic File Access Modes

1. Read Mode (“r”)

#include <stdio.h>

int main() {
    FILE *file;
    char buffer[100];
    
    printf("=== Read Mode Demo ===\n");
    
    // Create a test file first
    file = fopen("test_read.txt", "w");
    if (file != NULL) {
        fprintf(file, "Line 1: Hello World\n");
        fprintf(file, "Line 2: C Programming\n");
        fprintf(file, "Line 3: File Operations\n");
        fclose(file);
    }
    
    // Open file in read mode
    file = fopen("test_read.txt", "r");
    if (file == NULL) {
        printf("Error: Cannot open file for reading\n");
        return 1;
    }
    
    printf("Reading file contents:\n");
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("%s", buffer);
    }
    
    fclose(file);
    
    // Attempt to write to read-only file (will fail)
    file = fopen("test_read.txt", "r");
    if (file != NULL) {
        // This operation is not allowed in read mode
        int result = fprintf(file, "This won't work");
        if (result < 0) {
            printf("Write operation failed (expected in read mode)\n");
        }
        fclose(file);
    }
    
    return 0;
}

2. Write Mode (“w”)

#include <stdio.h>

int main() {
    FILE *file;
    char data[][50] = {
        "Write mode example",
        "This overwrites existing content",
        "Creates new file if doesn't exist"
    };
    
    printf("=== Write Mode Demo ===\n");
    
    // Open file in write mode
    file = fopen("test_write.txt", "w");
    if (file == NULL) {
        printf("Error: Cannot open file for writing\n");
        return 1;
    }
    
    printf("Writing to file...\n");
    for (int i = 0; i < 3; i++) {
        fprintf(file, "%s\n", data[i]);
        printf("Written: %s\n", data[i]);
    }
    
    fclose(file);
    
    // Open again to demonstrate overwriting
    file = fopen("test_write.txt", "w");
    if (file != NULL) {
        fprintf(file, "Previous content was overwritten\n");
        fclose(file);
        printf("File overwritten with new content\n");
    }
    
    // Verify the overwrite
    file = fopen("test_write.txt", "r");
    if (file != NULL) {
        char buffer[100];
        printf("Current file content:\n");
        while (fgets(buffer, sizeof(buffer), file) != NULL) {
            printf("%s", buffer);
        }
        fclose(file);
    }
    
    return 0;
}

3. Append Mode (“a”)

#include <stdio.h>

int main() {
    FILE *file;
    
    printf("=== Append Mode Demo ===\n");
    
    // Create initial file
    file = fopen("test_append.txt", "w");
    if (file != NULL) {
        fprintf(file, "Initial content\n");
        fclose(file);
        printf("Initial file created\n");
    }
    
    // Open in append mode
    file = fopen("test_append.txt", "a");
    if (file == NULL) {
        printf("Error: Cannot open file for appending\n");
        return 1;
    }
    
    // Add content to end of file
    fprintf(file, "Appended line 1\n");
    fprintf(file, "Appended line 2\n");
    fprintf(file, "Appended line 3\n");
    fclose(file);
    printf("Content appended to file\n");
    
    // Read entire file to show append result
    file = fopen("test_append.txt", "r");
    if (file != NULL) {
        char buffer[100];
        printf("Complete file content:\n");
        while (fgets(buffer, sizeof(buffer), file) != NULL) {
            printf("%s", buffer);
        }
        fclose(file);
    }
    
    return 0;
}

Combined Access Modes

1. Read/Write Mode (“r+“)

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

int main() {
    FILE *file;
    char buffer[100];
    
    printf("=== Read/Write Mode Demo ===\n");
    
    // Create test file with initial content
    file = fopen("test_rw.txt", "w");
    if (file != NULL) {
        fprintf(file, "Original line 1\n");
        fprintf(file, "Original line 2\n");
        fprintf(file, "Original line 3\n");
        fclose(file);
    }
    
    // Open in read/write mode
    file = fopen("test_rw.txt", "r+");
    if (file == NULL) {
        printf("Error: Cannot open file for read/write\n");
        return 1;
    }
    
    // Read current content
    printf("Current content:\n");
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("%s", buffer);
    }
    
    // Move to beginning and overwrite first line
    rewind(file);
    fprintf(file, "Modified line 1\n");
    
    // Move to end and append
    fseek(file, 0, SEEK_END);
    fprintf(file, "Added line 4\n");
    
    fclose(file);
    
    // Read modified file
    file = fopen("test_rw.txt", "r");
    if (file != NULL) {
        printf("\nModified content:\n");
        while (fgets(buffer, sizeof(buffer), file) != NULL) {
            printf("%s", buffer);
        }
        fclose(file);
    }
    
    return 0;
}

2. Write/Read Mode (“w+“)

#include <stdio.h>

int main() {
    FILE *file;
    char buffer[100];
    
    printf("=== Write/Read Mode Demo ===\n");
    
    // Open in write/read mode (creates new file or truncates existing)
    file = fopen("test_wr.txt", "w+");
    if (file == NULL) {
        printf("Error: Cannot open file for write/read\n");
        return 1;
    }
    
    // Write data to file
    fprintf(file, "Line 1: Write/Read mode\n");
    fprintf(file, "Line 2: Can read and write\n");
    fprintf(file, "Line 3: File was truncated\n");
    printf("Data written to file\n");
    
    // Move to beginning to read
    rewind(file);
    
    // Read the data we just wrote
    printf("Reading back the data:\n");
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("%s", buffer);
    }
    
    // Write more data at current position
    fprintf(file, "Line 4: Added at end\n");
    
    // Read all content again
    rewind(file);
    printf("\nComplete content:\n");
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("%s", buffer);
    }
    
    fclose(file);
    return 0;
}

3. Append/Read Mode (“a+“)

#include <stdio.h>

int main() {
    FILE *file;
    char buffer[100];
    
    printf("=== Append/Read Mode Demo ===\n");
    
    // Create initial file
    file = fopen("test_ar.txt", "w");
    if (file != NULL) {
        fprintf(file, "Existing line 1\n");
        fprintf(file, "Existing line 2\n");
        fclose(file);
    }
    
    // Open in append/read mode
    file = fopen("test_ar.txt", "a+");
    if (file == NULL) {
        printf("Error: Cannot open file for append/read\n");
        return 1;
    }
    
    // Add content (always at end in append mode)
    fprintf(file, "Appended line 3\n");
    fprintf(file, "Appended line 4\n");
    printf("Content appended\n");
    
    // Move to beginning to read entire file
    rewind(file);
    
    printf("Complete file content:\n");
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("%s", buffer);
    }
    
    // Try to write at current position (will still append at end)
    fprintf(file, "This goes at the end\n");
    
    // Read complete file again
    rewind(file);
    printf("\nAfter additional write:\n");
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("%s", buffer);
    }
    
    fclose(file);
    return 0;
}

Binary Mode Modifiers

Binary Mode Operations

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

// Structure for binary operations
struct Student {
    int id;
    char name[50];
    float gpa;
};

int main() {
    FILE *file;
    struct Student students[3] = {
        {101, "Alice Johnson", 3.85},
        {102, "Bob Smith", 3.92},
        {103, "Carol Brown", 3.67}
    };
    struct Student readStudent;
    
    printf("=== Binary Mode Operations ===\n");
    
    // Write binary data ("wb" mode)
    file = fopen("students.dat", "wb");
    if (file == NULL) {
        printf("Error: Cannot open file for binary writing\n");
        return 1;
    }
    
    // Write array of structures
    size_t written = fwrite(students, sizeof(struct Student), 3, file);
    printf("Written %zu student records\n", written);
    fclose(file);
    
    // Read binary data ("rb" mode)
    file = fopen("students.dat", "rb");
    if (file == NULL) {
        printf("Error: Cannot open file for binary reading\n");
        return 1;
    }
    
    printf("\nReading student records:\n");
    printf("%-5s %-20s %-5s\n", "ID", "Name", "GPA");
    printf("--------------------------------\n");
    
    while (fread(&readStudent, sizeof(struct Student), 1, file) == 1) {
        printf("%-5d %-20s %-5.2f\n", 
               readStudent.id, readStudent.name, readStudent.gpa);
    }
    
    fclose(file);
    
    // Append binary data ("ab" mode)
    file = fopen("students.dat", "ab");
    if (file != NULL) {
        struct Student newStudent = {104, "David Wilson", 3.78};
        fwrite(&newStudent, sizeof(struct Student), 1, file);
        fclose(file);
        printf("\nNew student record appended\n");
    }
    
    // Read/Write binary mode ("rb+" mode)
    file = fopen("students.dat", "rb+");
    if (file != NULL) {
        // Read first record
        fread(&readStudent, sizeof(struct Student), 1, file);
        printf("\nFirst record: %s (GPA: %.2f)\n", readStudent.name, readStudent.gpa);
        
        // Modify and write back
        readStudent.gpa = 3.95;
        fseek(file, 0, SEEK_SET);  // Go back to beginning
        fwrite(&readStudent, sizeof(struct Student), 1, file);
        
        fclose(file);
        printf("First record updated\n");
    }
    
    return 0;
}

Text vs Binary Mode Comparison

Demonstrating Mode Differences

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

int main() {
    FILE *textFile, *binaryFile;
    char data[] = "Hello\r\nWorld\r\n";  // Data with carriage returns
    char buffer[100];
    
    printf("=== Text vs Binary Mode Comparison ===\n");
    
    // Write in text mode
    textFile = fopen("text_mode.txt", "w");
    if (textFile != NULL) {
        fputs(data, textFile);
        fclose(textFile);
    }
    
    // Write in binary mode
    binaryFile = fopen("binary_mode.txt", "wb");
    if (binaryFile != NULL) {
        fwrite(data, sizeof(char), strlen(data), binaryFile);
        fclose(binaryFile);
    }
    
    printf("Data written: %s", data);
    printf("Original length: %zu bytes\n", strlen(data));
    
    // Read in text mode
    textFile = fopen("text_mode.txt", "r");
    if (textFile != NULL) {
        printf("\nText mode read:\n");
        while (fgets(buffer, sizeof(buffer), textFile) != NULL) {
            printf("Line: %s", buffer);
        }
        fclose(textFile);
    }
    
    // Read in binary mode
    binaryFile = fopen("binary_mode.txt", "rb");
    if (binaryFile != NULL) {
        size_t bytesRead = fread(buffer, sizeof(char), sizeof(buffer)-1, binaryFile);
        buffer[bytesRead] = '\0';
        printf("\nBinary mode read:\n");
        printf("Read %zu bytes: %s", bytesRead, buffer);
        fclose(binaryFile);
    }
    
    return 0;
}

Mode Validation and Error Handling

Checking Mode Validity

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

// Function to test file mode operations
void testFileMode(const char* filename, const char* mode, const char* description) {
    FILE *file;
    
    printf("\nTesting %s mode (%s):\n", description, mode);
    
    file = fopen(filename, mode);
    if (file == NULL) {
        printf("  Error: %s\n", strerror(errno));
        return;
    }
    
    printf("  File opened successfully\n");
    
    // Test write operation
    if (strstr(mode, "w") || strstr(mode, "a") || strstr(mode, "+")) {
        int writeResult = fprintf(file, "Test write\n");
        if (writeResult > 0) {
            printf("  Write operation: SUCCESS\n");
        } else {
            printf("  Write operation: FAILED\n");
        }
    } else {
        printf("  Write operation: NOT ALLOWED\n");
    }
    
    // Test read operation
    if (strstr(mode, "r") || strstr(mode, "+")) {
        char buffer[100];
        rewind(file);
        if (fgets(buffer, sizeof(buffer), file) != NULL) {
            printf("  Read operation: SUCCESS\n");
        } else {
            printf("  Read operation: FAILED or EOF\n");
        }
    } else {
        printf("  Read operation: NOT ALLOWED\n");
    }
    
    fclose(file);
}

int main() {
    printf("=== File Mode Validation ===\n");
    
    // Create test file
    FILE *file = fopen("mode_test.txt", "w");
    if (file != NULL) {
        fprintf(file, "Initial content for testing\n");
        fclose(file);
    }
    
    // Test different modes
    testFileMode("mode_test.txt", "r", "Read");
    testFileMode("mode_test.txt", "w", "Write");
    testFileMode("mode_test.txt", "a", "Append");
    testFileMode("mode_test.txt", "r+", "Read/Write");
    testFileMode("mode_test.txt", "w+", "Write/Read");
    testFileMode("mode_test.txt", "a+", "Append/Read");
    
    // Test with non-existent file
    testFileMode("nonexistent.txt", "r", "Read non-existent");
    testFileMode("nonexistent.txt", "w", "Write non-existent");
    
    return 0;
}

File Mode Summary Table

Quick Reference

#include <stdio.h>

void printModeTable() {
    printf("=== File Access Modes Summary ===\n\n");
    
    printf("%-8s %-12s %-12s %-25s\n", "Mode", "Read", "Write", "Description");
    printf("----------------------------------------------------------------\n");
    printf("%-8s %-12s %-12s %-25s\n", "r", "Yes", "No", "Read only, file must exist");
    printf("%-8s %-12s %-12s %-25s\n", "w", "No", "Yes", "Write only, truncates/creates");
    printf("%-8s %-12s %-12s %-25s\n", "a", "No", "Yes", "Append only, creates if needed");
    printf("%-8s %-12s %-12s %-25s\n", "r+", "Yes", "Yes", "Read/write, file must exist");
    printf("%-8s %-12s %-12s %-25s\n", "w+", "Yes", "Yes", "Read/write, truncates/creates");
    printf("%-8s %-12s %-12s %-25s\n", "a+", "Yes", "Yes", "Read/append, creates if needed");
    
    printf("\nBinary mode modifier: Add 'b' (e.g., 'rb', 'wb', 'ab')\n");
    printf("- Text mode: Default, may translate line endings\n");
    printf("- Binary mode: No translation, exact byte handling\n");
}

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

Important Points

  1. Mode string determines file access permissions and behavior
  2. Read mode (“r”) requires file to exist, opens for input only
  3. Write mode (“w”) creates new file or truncates existing file
  4. Append mode (“a”) always writes at end of file
  5. Plus modifier (+) enables both read and write operations
  6. Binary modifier (b) prevents line ending translation
  7. File position varies by mode (beginning for r/w, end for a)
  8. Error checking essential for robust file operations

Best Practices

  1. Choose appropriate mode based on intended operations
  2. Always check if file opened successfully
  3. Use binary mode for non-text data
  4. Close files promptly after use
  5. Handle file positioning correctly in update modes
  6. Validate mode compatibility with required operations
  7. Consider file creation behavior for each mode
  8. Test with different scenarios including non-existent files

Summary

File access modes in C control how files are opened and what operations are permitted. Basic modes include read (r), write (w), and append (a), while combined modes (r+, w+, a+) allow both reading and writing. Binary mode modifier (b) handles raw data without translation. Understanding mode behavior is crucial for successful file operations and preventing data loss or access errors.


Part of BCA Programming with C Course (UGCOA22J201)