Intermediate · Structs, unions, enums and files · topic 35 of 60 · 25 min
Binary files and records
Explanation
Text versus binary
In a text file, the number 123456 is stored as the six characters "123456". In a binary file, an int 123456 is stored as its 4 raw bytes. Binary files are smaller and faster to read and write (no formatting or parsing), and every record can have a fixed size, but humans cannot read them in an editor.
Writing and reading records
typedef struct {
int roll;
char name[30];
float marks;
} Student;
Student list[3] = { {1, "Asha", 91.5f}, {2, "Ravi", 78.0f}, {3, "Meena", 85.5f} };
FILE *out = fopen("students.dat", "wb");
if (!out) { perror("students.dat"); return 1; }
size_t written = fwrite(list, sizeof list[0], 3, out); /* element size, count */
fclose(out);
Student s;
FILE *in = fopen("students.dat", "rb");
if (!in) { perror("students.dat"); return 1; }
while (fread(&s, sizeof s, 1, in) == 1) { /* read one record at a time */
printf("%d %s %.1f\n", s.roll, s.name, s.marks);
}
fclose(in);Random access with fseek and ftell
/* read record number k (0-based) directly */
int read_student(FILE *f, long k, Student *out) {
if (fseek(f, k * (long) sizeof *out, SEEK_SET) != 0) return -1; /* jump to the record */
return fread(out, sizeof *out, 1, f) == 1 ? 0 : -1;
}
fseek(f, 0, SEEK_END); /* go to the end */
long bytes = ftell(f); /* current position = file size in bytes */
long records = bytes / (long) sizeof(Student);
rewind(f); /* back to the start */| Call | Meaning |
|---|---|
| fseek(f, offset, SEEK_SET) | Move to offset bytes from the start |
| fseek(f, offset, SEEK_CUR) | Move relative to the current position |
| fseek(f, offset, SEEK_END) | Move relative to the end |
| ftell(f) | Current position in bytes |
| rewind(f) | Back to the start (and clear errors) |
Updating record k in place: open with "r+b", fseek to k * sizeof(Student), fwrite the new record. When switching between reading and writing on the same stream, call fseek (or fflush) in between, as the standard requires.
Text versus binary mode on Windows
On Windows, text mode translates "\n" to "\r\n" when writing and back when reading, and treats byte 26 (Ctrl+Z) as end of file in text mode. For binary data this corrupts the bytes, so always use "rb"/"wb". On Linux and macOS there is no difference, which is why the bug often appears only when code moves to Windows.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Binary files and records · 1/6
In this lesson you will store records in binary files.
Prefer a video by a teacher? Find free videos on “c binary file fread fwrite fseek ftell struct records” on YouTube ↗
In real life: A fixed-size record file for a small library
A school library program keeps each book as a fixed-size binary record (accession number, title, issued flag). To mark book number 1042 as issued, it seeks directly to that record and rewrites it, which stays fast even with thousands of books.
typedef struct { int accession; char title[60]; int issued; } Book;
int set_issued(const char *path, long index, int issued) {
FILE *f = fopen(path, "r+b");
if (!f) return -1;
Book b;
if (fseek(f, index * (long) sizeof b, SEEK_SET) != 0 || fread(&b, sizeof b, 1, f) != 1) { fclose(f); return -1; }
b.issued = issued;
fseek(f, index * (long) sizeof b, SEEK_SET); /* reposition before writing */
int ok = fwrite(&b, sizeof b, 1, f) == 1;
fclose(f);
return ok ? 0 : -1;
}Practice (0/3 done)
fread(arr, sizeof arr[0], 10, f) returns 7. What does it mean?
Simulate fixed-size records and seeking in JavaScript, which runs here: a "file" is an array of bytes and each record is RECORD_SIZE = 4 bytes. Write readRecord(file, k) that returns the k-th record as an array of 4 bytes (like fseek to k * 4 then fread), or null if the file does not contain a whole record k.
Write a tiny student database in C: add_student appends a Student record to students.dat ("ab"), list_students reads all records, get_student(k) uses fseek to read record k directly, and count_students uses fseek/ftell. Test with five students and print record 3 directly.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Pointers to structs and the arrow operatorStructs, unions, enums and files · same module
- Data types and their sizesGetting started with C
- Structs, value types and reference typesC# and .NET · Classes and objects
- Binary and decimal for networkingComputer Networking (CCNA level) · IPv4 addressing
- Records and pattern matchingC# and .NET · Inheritance, interfaces and records
- Structs: your own data typesRust Programming · Structs, enums and pattern matching
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
Which mode should a binary file be opened with for reading?
Answer: "rb"
b means binary (it matters on Windows).
What does ftell(f) return after fseek(f, 0, SEEK_END)?
Answer: The file size in bytes
The current position at the end.
Why is fwrite of a struct not a portable file format?
Answer: Padding, type sizes and byte order differ between compilers and machines
Write fields explicitly for portability.
What is "endianness"?
Answer: The order in which the bytes of a multi-byte number are stored
Little-endian vs big-endian.
Why does the compiler add padding to structs?Related
Answer: To keep members aligned for fast (or legal) access
Alignment.
Which operator accesses a member of a struct variable?Related
Which size is guaranteed to be 1 on every platform?Related
When is a struct a good choice?Related
Answer: For small, immutable, value-like data such as a point or money
Small, immutable values are the classic struct use.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- This is the last topic of “Structs, unions, enums and files”. The module exam comes next.
- Module 7 exam: Structs, unions, enums and files · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, The preprocessor, multi-file programs and make. 60 topics left in the course before the final exam.