fread() / fwrite()
| Since: | C89(1989) |
|---|
Functions for reading and writing binary data directly to and from a file. Unlike text mode, no newline conversion is performed, so you can accurately handle binary files such as images, audio, and struct data.
Syntax
// Reads binary data from a file. // Return value: the number of blocks read (check with feof() or ferror()). size_t fread(void *ptr, size_t size, size_t count, FILE *stream); // Writes binary data to a file. // Return value: the number of blocks written (if different from count, an error occurred). size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
Parameters
| Parameter | Description |
|---|---|
| ptr | The buffer to store data into (for reading), or the starting address of the data to write (for writing). |
| size | The size of one block in bytes. For a struct, pass sizeof(struct X). |
| count | The number of blocks to read or write. |
| stream | A FILE pointer opened with "rb" or "wb". |
Sample Code
sample_fread_fwrite.c
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int id;
double score;
} Record;
int main(void) {
// Writes struct data to a binary file.
Record rec = {42, 98.5};
FILE *fp = fopen("data.bin", "wb"); // Opens the file in binary write mode.
if (fp == NULL) {
perror("fopen");
return EXIT_FAILURE;
}
size_t written = fwrite(&rec, sizeof(Record), 1, fp);
if (written != 1) {
fprintf(stderr, "Write failed.\n");
}
fclose(fp);
// Reads struct data from the binary file.
Record rec2 = {0};
fp = fopen("data.bin", "rb"); // Opens the file in binary read mode.
if (fp == NULL) {
perror("fopen");
return EXIT_FAILURE;
}
size_t read_count = fread(&rec2, sizeof(Record), 1, fp);
fclose(fp);
if (read_count == 1) {
printf("id = %d\n", rec2.id); // Outputs: id = 42
printf("score = %.1f\n", rec2.score); // Outputs: score = 98.5
}
return 0;
}
gcc fread_fwrite.c -o fread_fwrite ./fread_fwrite id = 42 score = 98.5
fread_fwrite2.c — Writing and reading an array of structs in one call
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME 32
typedef struct {
int id;
char name[MAX_NAME];
float power;
} Fighter;
int main(void) {
Fighter fighters[] = {
{1, "Son Goku", 9000.0f},
{2, "Vegeta", 8000.0f},
{3, "Piccolo", 3500.0f},
};
int count = (int)(sizeof(fighters) / sizeof(fighters[0]));
// Write the entire array at once.
FILE *fp = fopen("fighters.bin", "wb");
if (fp == NULL) { perror("fopen"); return EXIT_FAILURE; }
fwrite(fighters, sizeof(Fighter), count, fp);
fclose(fp);
// Read the entire array at once.
Fighter loaded[3];
fp = fopen("fighters.bin", "rb");
if (fp == NULL) { perror("fopen"); return EXIT_FAILURE; }
size_t n = fread(loaded, sizeof(Fighter), count, fp);
fclose(fp);
for (size_t i = 0; i < n; i++) {
printf("id=%d name=%-10s power=%.1f\n",
loaded[i].id, loaded[i].name, loaded[i].power);
}
remove("fighters.bin");
return 0;
}
gcc fread_fwrite2.c -o fread_fwrite2 ./fread_fwrite2 id=1 name=Son Goku power=9000.0 id=2 name=Vegeta power=8000.0 id=3 name=Piccolo power=3500.0
fread_fwrite3.c — Appending to a binary file and reading all entries
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int id;
float score;
} Entry;
int main(void) {
// Initial write
Entry e1 = {1, 85.5f};
FILE *fp = fopen("scores.bin", "wb");
if (fp == NULL) { perror("fopen"); return EXIT_FAILURE; }
fwrite(&e1, sizeof(Entry), 1, fp);
fclose(fp);
// Append additional entries.
Entry e2 = {2, 92.0f};
Entry e3 = {3, 78.3f};
fp = fopen("scores.bin", "ab"); // "ab" = binary append mode
if (fp == NULL) { perror("fopen"); return EXIT_FAILURE; }
fwrite(&e2, sizeof(Entry), 1, fp);
fwrite(&e3, sizeof(Entry), 1, fp);
fclose(fp);
// Read all entries.
fp = fopen("scores.bin", "rb");
if (fp == NULL) { perror("fopen"); return EXIT_FAILURE; }
Entry buf;
while (fread(&buf, sizeof(Entry), 1, fp) == 1) {
printf("id=%d score=%.1f\n", buf.id, buf.score);
}
fclose(fp);
remove("scores.bin");
return 0;
}
gcc fread_fwrite3.c -o fread_fwrite3 ./fread_fwrite3 id=1 score=85.5 id=2 score=92.0 id=3 score=78.3
Notes
Always specify binary mode ("rb", "wb", "ab") when opening a file. Opening in text mode causes automatic newline conversion ('\n' ↔ "\r\n") on Windows, which will corrupt binary data.
If the return value of fread() is less than the requested count, it means either the end of file (EOF) was reached or an error occurred. Use feof() / ferror() to determine the cause.
Reading or writing multiple blocks at once reduces the number of system calls and improves performance. You can control the file position with fseek().
If you find any errors or copyright issues, please contact us.