Binary Files
So far every file example has dealt with human-readable text. Binary mode instead reads and writes raw bytes exactly as they are laid out in memory — no text formatting, no interpretation, just a direct copy of bits to and from disk.
Text Mode vs Binary Mode
The difference is selected by adding b to the fopen mode string: "rb", "wb", "ab", "rb+", and so on, versus the plain "r", "w", "a" used for text.
fread() and fwrite()
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *fp); size_t fread(void *ptr, size_t size, size_t count, FILE *fp);
Both functions move count items of size bytes each, as one raw block of memory — no text formatting, no interpretation of the bytes involved. This makes them the natural fit for saving and loading structs, arrays, and other fixed-layout data directly.
Worked Example: An Array of Structs
#include <stdio.h>
typedef struct {
char name[20];
int score;
} Player;
int main(void)
{
Player players[3] = {
{"Alice", 95},
{"Bob", 87},
{"Carla", 91},
};
/* Write all three structs, raw, to a binary file */
FILE *fp = fopen("players.bin", "wb");
if (fp == NULL) {
printf("Could not open file for writing.\n");
return 1;
}
fwrite(players, sizeof(Player), 3, fp);
fclose(fp);
/* Read them back into a fresh array */
Player loaded[3];
fp = fopen("players.bin", "rb");
if (fp == NULL) {
printf("Could not open file for reading.\n");
return 1;
}
size_t itemsRead = fread(loaded, sizeof(Player), 3, fp);
fclose(fp);
for (size_t i = 0; i < itemsRead; i++) {
printf("%s: %d\n", loaded[i].name, loaded[i].score);
}
return 0;
}Alice: 95 Bob: 87 Carla: 91
fwrite copies the exact in-memory bytes of the players array to disk in one call, and fread copies them straight back into loaded — no parsing, no formatting, just a byte-for-byte round trip.
Aspect | Text I/O (fprintf/fscanf/fgets) | Binary I/O (fread/fwrite) |
|---|---|---|
Format | Human-readable characters | Raw memory bytes |
Speed | Slower — formatting/parsing overhead | Faster — direct memory copy |
Portability of the data | Very portable (plain text) | Not guaranteed portable across machines |
Typical use | Config files, logs, CSV, human-edited data | Saving/loading structs, images, custom binary formats |
Use binary mode +
fread/fwritefor fast, exact in-memory-layout persistence on a single platform/compiler combinationUse text mode for anything meant to be portable, human-readable, or edited by hand
For a binary format that must be portable, define an explicit byte layout (fixed-width types, defined endianness) rather than dumping raw structs