Shiklo Tools
PDF40
Image20
Calculators & Converters25
Text & Writing13
Developer26
Video14
Audio14
Document14
Data & Spreadsheet12
Web & SEO9
OCR & Scanning5
Archive & File12
Security & Privacy23
Health & Medical29
QR & Barcode5

C Files: Read

Reading a file works like reading the keyboard, with a FILE * instead of stdin. Open the file with mode "r", read until the end, and close it.

Line by line with fgets

fgets(buffer, size, file) reads one line, including its '\n', and returns NULL at the end of the file. That makes it a natural loop condition.

#include <stdio.h>

int main(void) {
    FILE *out = fopen("poem.txt", "w");
    if (out == NULL) return 1;
    fputs("Roses are red,\nviolets are blue,\nC is quite fast,\nand so are you.\n", out);
    fclose(out);

    FILE *in = fopen("poem.txt", "r");
    if (in == NULL) return 1;
    char line[100];
    int number = 1;
    while (fgets(line, sizeof line, in) != NULL) {
        printf("%d: %s", number++, line);
    }
    fclose(in);
    return 0;
}
Output
1: Roses are red,
2: violets are blue,
3: C is quite fast,
4: and so are you.

Values with fscanf

fscanf reads values the way scanf does and returns how many it read, so a loop can continue while it reads a full record:

#include <stdio.h>

int main(void) {
    FILE *out = fopen("marks.txt", "w");
    if (out == NULL) return 1;
    fprintf(out, "Asha 91\nRavi 78\nMeera 85\n");
    fclose(out);

    FILE *in = fopen("marks.txt", "r");
    if (in == NULL) return 1;
    char name[20];
    int mark, total = 0, count = 0;
    while (fscanf(in, "%19s %d", name, &mark) == 2) {
        printf("%s scored %d\n", name, mark);
        total += mark;
        count++;
    }
    fclose(in);
    printf("Average of %d students: %.2f\n", count, (double)total / count);
    return 0;
}
Output
Asha scored 91
Ravi scored 78
Meera scored 85
Average of 3 students: 84.67

Character by character

fgetc(file) returns one character, or EOF at the end. Store it in an int, not a char, because EOF is not a character value.

#include <stdio.h>

int main(void) {
    FILE *out = fopen("note.txt", "w");
    if (out == NULL) return 1;
    fputs("one two\nthree\n", out);
    fclose(out);

    FILE *in = fopen("note.txt", "r");
    if (in == NULL) return 1;
    int c, lines = 0, chars = 0;
    while ((c = fgetc(in)) != EOF) {
        chars++;
        if (c == '\n') lines++;
    }
    fclose(in);
    printf("%d characters, %d lines\n", chars, lines);
    return 0;
}
Output
14 characters, 2 lines

A file that does not exist

fopen returns NULL when the file is missing. A friendly program says so instead of crashing:

#include <stdio.h>

int main(void) {
    FILE *f = fopen("missing.txt", "r");
    if (f == NULL) {
        printf("missing.txt was not found.\n");
        return 1;
    }
    fclose(f);
    return 0;
}
Output
missing.txt was not found.

A classic mistake: while (!feof(f))

Many old examples read a file like this:

while (!feof(f)) {
    fgets(line, sizeof line, f);
    printf("%s", line);
}

It looks right but prints the last line twice. feof only becomes true after a read has failed at the end of the file, so the loop runs one extra time with the old contents of line. The fix is the pattern used above: test the result of the read itself, as in while (fgets(...) != NULL) or while (fscanf(...) == 2). feof is useful afterwards, to tell whether the loop stopped at the end of the file or because of an error.

Text and binary files

The functions on this page work with text files, where data is stored as readable characters. Programs can also store raw bytes, for example a whole array of structures, with fwrite and fread on a file opened in "wb" and "rb" mode. Binary files are smaller and faster, but cannot be read in an editor and may differ between computers, so text files are the safer choice for data people need to read.

Practice exercises

  1. Write a program that reads names.txt and prints how many names it contains.
  2. Copy one text file into another line by line with fgets and fputs.
  3. Count the words in a file by counting the switches from spaces to letters.