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
- Mode string determines file access permissions and behavior
- Read mode (“r”) requires file to exist, opens for input only
- Write mode (“w”) creates new file or truncates existing file
- Append mode (“a”) always writes at end of file
- Plus modifier (+) enables both read and write operations
- Binary modifier (b) prevents line ending translation
- File position varies by mode (beginning for r/w, end for a)
- Error checking essential for robust file operations
Best Practices
- Choose appropriate mode based on intended operations
- Always check if file opened successfully
- Use binary mode for non-text data
- Close files promptly after use
- Handle file positioning correctly in update modes
- Validate mode compatibility with required operations
- Consider file creation behavior for each mode
- 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)