SyntaxStudy
Sign Up
C fopen, fclose, and Text File I/O
C Beginner 1 min read

fopen, fclose, and Text File I/O

C's file I/O is stream-based, built around the `FILE` type defined in ``. The `fopen()` function opens a file and returns a `FILE *` stream, or `NULL` on failure. The second argument is a mode string: `"r"` for reading, `"w"` for writing (truncates existing content), `"a"` for appending, and `"r+"` or `"w+"` for read-write access. Adding `"b"` to any mode (e.g. `"rb"`) opens the file in binary mode. Text-mode functions include `fprintf()` for formatted output (like `printf` but to a file), `fputs()` for writing a string, `fgets()` for reading a line, and `fscanf()` for formatted input. `fgetc()` and `fputc()` read and write single characters. All of these return error indicators — `fgets` returns `NULL` at end-of-file or on error, `feof()` and `ferror()` distinguish the two cases. Always close files with `fclose()` when done. The OS typically flushes buffered writes when you close a file; without closing, buffered data may never reach disk. In long-running programs that process many files, failing to close each file causes file descriptor leaks, which can eventually prevent the process from opening new files. Using the `goto cleanup` pattern ensures `fclose` is called on all exit paths.
Example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int write_csv(const char *path)
{
    FILE *f = fopen(path, "w");
    if (!f) { perror(path); return -1; }

    fprintf(f, "name,score,grade\n");
    fprintf(f, "Alice,%d,%s\n", 95, "A");
    fprintf(f, "Bob,%d,%s\n",   82, "B");
    fprintf(f, "Carol,%d,%s\n", 74, "C");

    fclose(f);
    return 0;
}

int read_csv(const char *path)
{
    FILE *f = fopen(path, "r");
    if (!f) { perror(path); return -1; }

    char line[128];
    int  row = 0;

    while (fgets(line, sizeof(line), f)) {
        /* Strip trailing newline */
        line[strcspn(line, "\n")] = '\0';

        if (row == 0) {
            printf("Header: %s\n", line);
        } else {
            char name[32]; int score; char grade[4];
            if (sscanf(line, "%31[^,],%d,%3s", name, &score, grade) == 3)
                printf("  %-8s score=%-3d grade=%s\n",
                       name, score, grade);
        }
        row++;
    }

    if (ferror(f)) perror("read error");
    fclose(f);
    return 0;
}

int main(void)
{
    const char *path = "scores.csv";
    if (write_csv(path) == 0)
        read_csv(path);
    return EXIT_SUCCESS;
}