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
- Always check file operations for success/failure
- Close files after operations to free resources
- Use appropriate file modes for your needs
- Handle errors gracefully with meaningful messages
- Use binary mode for non-text data
- Validate file paths before opening
- 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)