C differentiates between two types of file I/O: Text Files (which handle data as sequences of characters, often with conversions for newlines) and Binary Files (which handle data as raw bytes, with no translation or formatting).
Binary files are used to store data exactly as it is represented in the computer’s memory, making them faster and more compact for storing numerical data or complex structures.
1. Binary File Modes
To open a file for binary I/O, you append a b to the standard file mode string:
| Mode String | Purpose |
"rb" | Read binary file. |
"wb" | Write binary file (truncates existing content). |
"ab" | Append binary file. |
"r+b" or "rb+" | Open for both reading and writing (read/update). |
Example:
FILE *bin_fp = fopen("records.bin", "wb"); // Open for binary writing
if (bin_fp == NULL) {
// Handle error...
}
2. Binary I/O Functions (fread and fwrite)
Binary operations use two functions that read and write blocks of raw bytes, rather than formatted characters. They are ideal for reading/writing entire arrays or structures in one operation.
| Function | Purpose |
fwrite() | Writes a block of data from memory to the file. |
fread() | Reads a block of data from the file into memory. |
Syntax for both:
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
| Parameter | Description |
ptr | A pointer to the block of memory (the data source/destination). |
size | The size, in bytes, of a single data element to be read/written (often sizeof(dataType)). |
nmemb | The number of elements (records) to be read/written. |
stream | The file pointer (FILE *). |
3. Example: Writing a Structure to a Binary File
Writing a structure directly is the most common use case for binary I/O.
// Assume this struct is defined globally
struct Record {
int id;
float value;
};
// ... in main() or a function ...
struct Record rec = {101, 3.14f};
FILE *fp = fopen("records.bin", "wb");
// Write one element (rec) whose size is sizeof(struct Record)
fwrite(&rec, sizeof(struct Record), 1, fp);
fclose(fp);
4. Example: Reading a Structure from a Binary File
Reading the data back involves using fread() to place the raw bytes back into a structure variable.
struct Record rec_read;
FILE *fp = fopen("records.bin", "rb");
// Read one element of size sizeof(struct Record) into the address of rec_read
size_t records_read = fread(&rec_read, sizeof(struct Record), 1, fp);
if (records_read == 1) {
printf("Read ID: %d, Value: %.2f\n", rec_read.id, rec_read.value);
}
fclose(fp);
5. File Positioning (fseek, ftell, rewind)
These functions allow random access within a file, letting you jump to any record or position rather than reading sequentially.
| Function | Purpose |
fseek() | Sets the position of the next I/O operation. Allows moving the cursor forward or backward from a specific origin (start, current, or end of file). |
ftell() | Returns the current position of the file pointer (an offset in bytes from the start of the file). |
rewind() | Moves the file pointer back to the beginning of the file (equivalent to fseek(fp, 0, SEEK_SET)). |
