SyntaxStudy
Sign Up
C Binary Files: fread and fwrite
C Beginner 1 min read

Binary Files: fread and fwrite

Binary file I/O reads and writes raw bytes rather than formatted text. `fwrite(ptr, size, count, stream)` writes `count` elements of `size` bytes each from the buffer pointed to by `ptr`. `fread(ptr, size, count, stream)` reads up to `count` elements of `size` bytes each into the buffer. Both return the number of elements actually transferred, which may be less than requested at end-of-file or on error. Binary files are more compact and faster to read and write than text files because there is no conversion overhead. They are ideal for storing arrays of fixed-size records, image data, audio samples, or any structured binary format. However, binary files are not human-readable, and they can have portability problems related to endianness (byte order) and struct padding when exchanged between different platforms or architectures. The `fseek()` function repositions the file stream to an arbitrary byte offset. `ftell()` returns the current position. `rewind()` resets to the beginning. Together these allow random access within a binary file — you can jump directly to the nth record without reading all preceding records. `fseek(f, 0, SEEK_END)` followed by `ftell(f)` is a common idiom to determine a file's size.
Example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char   name[32];
    int    id;
    double salary;
} Employee;

int save_employees(const char *path,
                   const Employee *arr, int n)
{
    FILE *f = fopen(path, "wb");
    if (!f) { perror(path); return -1; }

    size_t written = fwrite(arr, sizeof(Employee), (size_t)n, f);
    fclose(f);
    return (written == (size_t)n) ? 0 : -1;
}

int load_employees(const char *path,
                   Employee *arr, int max, int *out_n)
{
    FILE *f = fopen(path, "rb");
    if (!f) { perror(path); return -1; }

    /* Determine record count from file size */
    fseek(f, 0, SEEK_END);
    long size = ftell(f);
    rewind(f);

    *out_n = (int)(size / (long)sizeof(Employee));
    if (*out_n > max) *out_n = max;

    size_t read = fread(arr, sizeof(Employee), (size_t)*out_n, f);
    fclose(f);
    return (read == (size_t)*out_n) ? 0 : -1;
}

int main(void)
{
    Employee staff[] = {
        {"Alice", 1, 75000.0},
        {"Bob",   2, 68000.0},
        {"Carol", 3, 82000.0}
    };

    save_employees("staff.bin", staff, 3);
    printf("Saved %d employees.\n", 3);

    Employee loaded[10];
    int n = 0;
    if (load_employees("staff.bin", loaded, 10, &n) == 0) {
        printf("Loaded %d employees:\n", n);
        for (int i = 0; i < n; i++)
            printf("  id=%d  name=%-8s  salary=%.2f\n",
                   loaded[i].id, loaded[i].name, loaded[i].salary);
    }
    return EXIT_SUCCESS;
}