PY
C

Python to C

10 lessons

Progress0%
1Variables & Types2Functions3Lists → Arrays4Memory Management5String Handling6Structs7Preprocessor8File I/O9Pointers and Manual Memory10Build System: Makefile
All Mirror Courses
PY
C
File I/O
MirrorLesson 8 of 10
Lesson 8

File I/O

fopen/fclose, reading/writing text and binary files, error handling with errno

Introduction

In this lesson, you'll learn about file i/o in C. Coming from Python, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.

Mirror Card
PY
From Python:

In Python, you're familiar with fopen/fclose, reading/writing text and binary files, error handling with errno.

C
In C:

C has its own approach to fopen/fclose, reading/writing text and binary files, error handling with errno, which we'll explore step by step.

The C Way

Let's see how C handles this concept. Here's a typical example:

C
C Example
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

int main(void) {
    // Open file — always check for NULL
    FILE *f = fopen("data.txt", "r");
    if (f == NULL) {
        fprintf(stderr, "Error opening file: %s\n", strerror(errno));
        return 1;
    }

    // Read line by line
    char line[256];
    while (fgets(line, sizeof(line), f) != NULL) {
        printf("%s", line);  // fgets includes '\n'
    }
    fclose(f);  // MUST close!

    // Write text
    FILE *out = fopen("out.txt", "w");  // "a" for append
    if (out == NULL) { perror("fopen"); return 1; }
    fprintf(out, "Hello, %s!\n", "World");
    fputs("another line\n", out);
    fclose(out);

    // Binary read/write
    FILE *img = fopen("img.png", "rb");
    FILE *dst = fopen("copy.png", "wb");
    char buf[4096];
    size_t n;
    while ((n = fread(buf, 1, sizeof(buf), img)) > 0) {
        fwrite(buf, 1, n, dst);
    }
    fclose(img);
    fclose(dst);

    return 0;
}

Comparing to Python

Here's how you might have written similar code in Python:

PY
Python (What you know)
# Text read
with open("data.txt", "r", encoding="utf-8") as f:
    content = f.read()          # entire file
    # lines = f.readlines()     # list of lines
    # for line in f: ...

# Text write
with open("out.txt", "w") as f:
    f.write("Hello!\n")

# Append
with open("log.txt", "a") as f:
    f.write("entry\n")

# Binary read/write
with open("img.png", "rb") as f:
    data = f.read()
with open("copy.png", "wb") as f:
    f.write(data)

# JSON
import json
with open("data.json") as f:
    obj = json.load(f)

# Check existence
from pathlib import Path
if Path("file.txt").exists():
    ...
Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

C
In C:

fopen returns NULL on failure; always check — no automatic exception

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

C
In C:

fgets reads one line at a time (including newline); read() in Python reads all

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

C
In C:

MUST call fclose() explicitly — no context manager auto-close in C

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

C
In C:

fprintf for formatted write (like Python f-strings); fputs for plain strings

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

C
In C:

Binary mode: 'rb'/'wb' — critical on Windows (text mode translates \r\n)

Step-by-Step Breakdown

1. Opening and Closing Files

fopen returns a FILE* or NULL on error. Always check for NULL and always call fclose(). No automatic cleanup in C.

PY
Python
with open("file.txt") as f:
    # auto-closes
C
C
FILE *f = fopen("file.txt", "r");
if (f == NULL) { perror("fopen"); return 1; }
// ... use f ...
fclose(f); // MUST call or file handle leaks
Common Pitfall
Forgetting fclose() leaks file handles and may cause buffered writes to be lost.

2. Reading Lines

fgets reads up to n-1 chars including the newline. EOF is detected by fgets returning NULL.

PY
Python
for line in f:
    process(line)
C
C
char buf[256];
while (fgets(buf, sizeof(buf), f) != NULL) {
    // buf includes '\n' at end
    buf[strcspn(buf, "\n")] = '\0'; // strip newline
    process(buf);
}

3. Formatted Writing

fprintf writes to a file like printf to stdout. Use %s, %d, %f format specifiers.

PY
Python
f.write(f"name={name}, age={age}\n")
C
C
fprintf(f, "name=%s, age=%d\n", name, age);

4. Binary Files

Use 'rb'/'wb' for binary files. fread/fwrite operate on raw bytes, perfect for copying or processing non-text files.

PY
Python
with open("img.png", "rb") as f:
    data = f.read()
C
C
FILE *f = fopen("img.png", "rb");
char buf[4096]; size_t n;
while ((n = fread(buf, 1, sizeof(buf), f)) > 0) {
    process(buf, n);
}
fclose(f);
Rule of Thumb
Always use 'b' mode for non-text files on Windows — text mode translates \r\n and corrupts binary data.

Common Mistakes

When coming from Python, developers often make these mistakes:

  • fopen returns NULL on failure; always check — no automatic exception
  • fgets reads one line at a time (including newline); read() in Python reads all
  • MUST call fclose() explicitly — no context manager auto-close in C
Common Pitfall
Don't assume C works exactly like Python. While the concepts may be similar, the syntax and behavior can differ significantly.

Key Takeaways

  • fopen returns NULL on failure — always check; fclose must be called explicitly
  • fgets reads one line (including \n); fread/fwrite for binary data
  • fprintf for formatted output to file; fputs for plain strings
  • Binary mode 'rb'/'wb' essential on Windows to avoid \r\n translation
Rule of Thumb
The best way to learn is by doing. Try rewriting some of your Python code in C to practice these concepts.
PreviousNext