Skip to content

Intermediate · Structs, unions, enums and files · topic 34 of 60 · 30 min

Reading and writing text files

Explanation

fopen(path, mode) opens a file and returns a FILE *, or NULL on failure; always check it and report the reason with perror. Modes include "r" (read), "w" (write, truncating), "a" (append) and "r+". Write with fprintf and fputs, read with fgets or fscanf, and always fclose. Loop on the read function's return value, not on feof.

Opening and closing

c
#include <stdio.h>

FILE *fp = fopen("orders.txt", "r");
if (fp == NULL) {
    perror("orders.txt");         /* prints e.g. "orders.txt: No such file or directory" */
    return 1;
}
/* … read … */
fclose(fp);
ModeMeaningIf the file existsIf it does not
"r"readopens itfails (NULL)
"w"writeERASES it (truncates to 0)creates it
"a"appendwrites go to the endcreates it
"r+"read and writeopens itfails
"w+"read and writeerases itcreates it
add "b"binary mode ("rb", "wb")no newline translation (topic 5)
Careful: Opening an existing file with "w" erases its contents immediately, before you write anything. Many people have lost data by opening a log or a database file with "w" instead of "a" or "r+". Double-check the mode.

Writing text

c
FILE *out = fopen("bill.txt", "w");
if (!out) { perror("bill.txt"); return 1; }
fprintf(out, "%-10s %8s\n", "Item", "Amount");
fprintf(out, "%-10s %8.2f\n", "Rice", 340.0);
fputs("Thank you!\n", out);
if (fclose(out) != 0) perror("closing bill.txt");   /* fclose flushes; it can fail (disk full) */

Reading line by line

c
char line[256];
int n = 0;
while (fgets(line, sizeof line, fp) != NULL) {   /* loop on the read result */
    line[strcspn(line, "\n")] = '\0';
    printf("%d: %s\n", ++n, line);
}
if (ferror(fp)) perror("read error");

Reading formatted data

c
/* marks.txt: one "name marks" pair per line, e.g. "Asha 91" */
char name[30];
int marks;
while (fscanf(fp, "%29s %d", name, &marks) == 2) {   /* stop when 2 values are not read */
    printf("%s scored %d\n", name, marks);
}

The feof mistake

c
/* WRONG: processes the last line twice (or garbage once) */
while (!feof(fp)) {
    fgets(line, sizeof line, fp);
    puts(line);
}
feof only becomes true AFTER a read has already failed at the end. Loop on the return value of fgets / fscanf / fread instead, and use feof/ferror afterwards to learn WHY the loop stopped.

Standard streams

Three FILE * streams are always open: stdin (keyboard or piped input), stdout (normal output) and stderr (error messages). Print errors with fprintf(stderr, …) or perror, so they appear even when stdout is redirected to a file.

Think of it like this: A FILE * is like a library issue slip: fopen gets you the book and the slip, reading moves your bookmark forward, and fclose returns the book. Opening with "w" is like being handed a book whose pages are torn out the moment you borrow it.
Tip: Check every fopen, every write if the data matters, and fclose. Write errors (a full disk) often surface only at fclose.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Reading and writing text files · 1/6

Text files

In this lesson you will read and write text files in C.

Prefer a video by a teacher? Find free videos on “c file handling fopen fprintf fgets fscanf fclose tutorial” on YouTube ↗

In real life: A daily attendance log

A small coaching institute's attendance program appends one line per student per day to attendance.txt in "a" mode, so earlier days are never overwritten, and a separate report program reads the file line by line to count each student's days present.

c
FILE *log = fopen("attendance.txt", "a");
if (!log) { perror("attendance.txt"); return 1; }
fprintf(log, "%s,%s,%s\n", "2026-10-19", "ROLL-0042", "P");
fclose(log);

Practice (0/3 done)

Task 1 · Question

Which mode adds lines to the end of an existing log without erasing it?

Task 2 · Question

A file has 3 lines and count starts at 0. What is count after this loop? while (!feof(fp)) { if (fgets(buf, sizeof buf, fp)) count++; }

Task 3 · Practice

Write a program that reads a text file marks.txt of lines "name marks", prints each line with a running count, writes students with marks >= 60 into passed.txt, and prints the class average. Handle a missing input file with perror and exit code 1, and close both files.

Quick quiz

Question 1

1.What does fopen return when the file cannot be opened?

Question 2

2.What does perror("x.txt") print?

Question 3

3.Which stream should error messages go to?

Question 4

4.Opening an existing important file with "w"…

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What does fopen return when the file cannot be opened?

Answer: NULL

Check and use perror.

What does perror("x.txt") print?

Answer: "x.txt: " followed by the system's reason (from errno)

For example "No such file or directory".

Which stream should error messages go to?

Answer: stderr

stderr is not redirected with stdout.

Opening an existing important file with "w"…

Answer: Erases its contents immediately

Truncation happens at open time.

What does read return at end of file?Related

Answer: 0

0 means no more data; -1 means an error.

From C on Linux: files and processes with system calls

You open an existing file with mode "w". What happens to its old content?Related

Answer: It is erased as soon as the file opens

"w" empties the file immediately, even before you write anything.

From Working with files

Files.writeString(path, text) on an existing file, with no options…Related

Answer: Replaces the content

The default options create or truncate; use APPEND to add.

From Reading and writing files

fgets returns NULL when…Related

Answer: End of input is reached (or an error occurs) before reading anything

Check it before using the buffer.

From Reading strings safely

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 1 more topic in “Structs, unions, enums and files” before its exam: Binary files and records.
  2. Module 7 exam: Structs, unions, enums and files · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, The preprocessor, multi-file programs and make. 60 topics left in the course before the final exam.

← Previous: Unions, enums and memory layout