devnotes.

Reading and Writing Files

C's <stdio.h> treats files through a FILE* handle, opened with a specific mode describing how you intend to use it.

#include <stdio.h>

int main(void) {
    FILE *out = fopen("notes.txt", "w");  // "w" = write (creates/overwrites)
    if (out == NULL) {
        perror("Failed to open file");
        return 1;
    }
    fprintf(out, "Line %d\n", 1);
    fclose(out);

    FILE *in = fopen("notes.txt", "r");   // "r" = read
    if (in == NULL) { perror("Failed to open file"); return 1; }

    char line[100];
    while (fgets(line, sizeof(line), in) != NULL) {
        printf("Read: %s", line);
    }
    fclose(in);
    return 0;
}

fopen returns NULL if the file can't be opened (wrong path, missing permissions, disk full) — always check before using the handle, and perror prints a human-readable reason based on the system's last error, saving you from guessing why it failed.

Common modes: "r" (read, file must exist), "w" (write, creates a new file or truncates an existing one — destroying its old contents), "a" (append, writes are added to the end without erasing what's there). fgets is the safe, standard way to read a line at a time, since it takes a buffer size and never overflows it, unlike scanf("%s", ...).

Every successful fopen must be matched with fclose — this flushes any buffered output to disk and releases the operating system's file handle, and skipping it can lose the last bit of buffered data or exhaust the (limited) number of files a program is allowed to have open at once.

Reading and Writing Files in C with fopen and fgets | DevNotes