C File Handling: Mastering I/O with fopen, fprintf, fread, and fseek
C File Handling
This tutorial guides you through file I/O in C, covering standard and binary operations with clear, practical examples.
A file is a logical container on a computer’s storage that holds data for long‑term use.
Why Use Files?
- Data persists after a program terminates, preventing loss of information.
- Large data sets can be stored once and accessed quickly via a few C commands.
- Files can be moved between computers without modification.
Types of Files
In C, you’ll encounter two primary file types:
- Text files
- Binary files
Text Files
Plain‑text files (e.g., .txt) are editable with any text editor. They’re easy to read, maintain, and transfer but occupy more space and offer minimal security.
Binary Files
Binary files (commonly .bin) store data as raw bytes (0s and 1s). They are compact, not human‑readable, and provide better data integrity and security.
Core File Operations
Regardless of type, C file handling revolves around four operations:
- Create a new file
- Open an existing file
- Close a file
- Read from or write to a file
Preparing a File Pointer
All file operations require a FILE * pointer to reference the open file:
FILE *fptr;
Opening Files: Creation and Editing
The fopen() function (declared in stdio.h) opens a file and returns a FILE * pointer. Its syntax is:
fptr = fopen("filename", "mode");
Example usage:
fopen("E:\\cprogram\\newprogram.txt", "w");
fopen("E:\\cprogram\\oldprogram.bin", "rb");
Explanation:
newprogram.txtis created (if absent) and opened for writing in mode'w', which overwrites any existing content.oldprogram.binis opened for binary reading only in mode'rb'; attempting to write will fail.
| Mode | Meaning | Behavior if file is missing |
|---|---|---|
r | Open for reading | Returns NULL |
rb | Open for binary reading | Returns NULL |
w | Open for writing (overwrite) | Creates file if absent |
wb | Open for binary writing (overwrite) | Creates file if absent |
a | Open for appending | Creates file if absent |
ab | Open for binary appending | Creates file if absent |
r+ | Read and write | Returns NULL |
rb+ | Read and write in binary | Returns NULL |
w+ | Read and write (overwrite) | Creates file if absent |
wb+ | Read and write in binary (overwrite) | Creates file if absent |
a+ | Read and append | Creates file if absent |
ab+ | Read and binary append | Creates file if absent |
Closing a File
After all I/O operations, always close the file with fclose() to release resources and flush buffers:
fclose(fptr);
Text File I/O
Text files are handled with fprintf() and fscanf(), the file‑based counterparts of printf() and scanf(). They require a FILE * pointer as the first argument.
Example 1: Write to a Text File
#include <stdio.h>
#include <stdlib.h>
int main() {
int num;
FILE *fptr;
// Adjust the path for your OS
fptr = fopen("C:\\program.txt", "w");
if (fptr == NULL) {
printf("Error opening file\n");
exit(EXIT_FAILURE);
}
printf("Enter a number: ");
scanf("%d", &num);
fprintf(fptr, "%d", num);
fclose(fptr);
return 0;
}
This program captures an integer from the user and writes it to program.txt.
Example 2: Read from a Text File
#include <stdio.h>
#include <stdlib.h>
int main() {
int num;
FILE *fptr;
fptr = fopen("C:\\program.txt", "r");
if (fptr == NULL) {
printf("Error opening file\n");
exit(EXIT_FAILURE);
}
fscanf(fptr, "%d", &num);
printf("Value read: %d\n", num);
fclose(fptr);
return 0;
}
Running this after the first example will display the stored integer.
Additional utilities such as fgetc() and fputc() follow the same pattern.
Binary File I/O
Binary files are manipulated with fwrite() for writing and fread() for reading. Both functions accept four arguments: pointer to data, size of each element, number of elements, and FILE * pointer.
Writing to a Binary File
fwrite(addressData, sizeData, numberData, filePointer);
Example 3: Write to a Binary File Using fwrite()
#include <stdio.h>
#include <stdlib.h>
struct threeNum {
int n1, n2, n3;
};
int main() {
int i;
struct threeNum num;
FILE *fptr;
fptr = fopen("C:\\program.bin", "wb");
if (fptr == NULL) {
printf("Error opening file\n");
exit(EXIT_FAILURE);
}
for (i = 1; i < 5; ++i) {
num.n1 = i;
num.n2 = 5 * i;
num.n3 = 5 * i + 1;
fwrite(&num, sizeof(struct threeNum), 1, fptr);
}
fclose(fptr);
return 0;
}
Reading from a Binary File
The corresponding fread() signature mirrors fwrite():
fread(addressData, sizeData, numberData, filePointer);
Example 4: Read from a Binary File Using fread()
#include <stdio.h>
#include <stdlib.h>
struct threeNum {
int n1, n2, n3;
};
int main() {
int i;
struct threeNum num;
FILE *fptr;
fptr = fopen("C:\\program.bin", "rb");
if (fptr == NULL) {
printf("Error opening file\n");
exit(EXIT_FAILURE);
}
for (i = 1; i < 5; ++i) {
fread(&num, sizeof(struct threeNum), 1, fptr);
printf("n1: %d\tn2: %d\tn3: %d\n", num.n1, num.n2, num.n3);
}
fclose(fptr);
return 0;
}
This program reproduces the data written in Example 3.
Random Access with fseek()
When a file contains many records, sequentially traversing to a specific entry can be inefficient. fseek() moves the file pointer to an arbitrary position, enabling direct access.
Syntax
fseek(FILE *stream, long int offset, int whence);
stream: pointer returned byfopen().offset: number of bytes to move.whence: starting point –SEEK_SET,SEEK_CUR, orSEEK_END.
| Constant | Meaning |
|---|---|
SEEK_SET | Offset starts from the file beginning. |
SEEK_CUR | Offset starts from the current cursor position. |
SEEK_END | Offset starts from the file end. |
Example 5: Reverse‑Order Reading with fseek()
#include <stdio.h>
#include <stdlib.h>
struct threeNum {
int n1, n2, n3;
};
int main() {
int i;
struct threeNum num;
FILE *fptr;
fptr = fopen("C:\\program.bin", "rb");
if (fptr == NULL) {
printf("Error opening file\n");
exit(EXIT_FAILURE);
}
// Move to the last record
fseek(fptr, -sizeof(struct threeNum), SEEK_END);
for (i = 1; i < 5; ++i) {
fread(&num, sizeof(struct threeNum), 1, fptr);
printf("n1: %d\tn2: %d\tn3: %d\n", num.n1, num.n2, num.n3);
// Step back two records (current + one more) to read the previous entry
fseek(fptr, -2 * sizeof(struct threeNum), SEEK_CUR);
}
fclose(fptr);
return 0;
}
This snippet demonstrates how to traverse a binary file in reverse, starting from the last record.
C Language
- File Cabinet: Design, Manufacturing, and Modern Use
- C++ File Handling: Mastering Open, Read, Write, and Close Operations
- File Operations in C# – A Practical Guide
- Understanding C Header Files: Types, Usage, and Best Practices
- Mastering Error Handling in C: Best Practices & Techniques
- Mastering File I/O in C++: Reading and Writing with fstream
- Mastering C# Exception Handling: Strategies & Best Practices
- Python File I/O: Mastering Input and Output Operations
- What Is a Mill File? Your Comprehensive Guide to the Essential Wood & Metalworking Tool
- Effortlessly Serve Static Files with Go: A Proven Approach