Beginner’s Guide: Master C File I/O with fopen, fread, fprintf

目次

1. Basics of File Operations in C

File operations are the program’s “means of interacting with the outside”

C is a system-oriented low-level language, yet it also provides practical file I/O functions as part of its standard library. File operations refer to the processing by which a program reads from and writes to files (text files or binary files) on a computer, and they are needed in situations such as the following.
  • Data persistence (saving data even after the program ends)
  • Logging (tracking execution details and errors)
  • Reading configuration from external files (enabling flexible configuration changes)
Thus, file operations are an essential technique for practical C programs.

Differences between Text Files and Binary Files

In C, there are mainly two types of files you can work with.
  • Text files (e.g., .txt) Files composed of human-readable character data. They are typically manipulated using functions such as fprintf and fscanf.
  • Binary files (e.g., .dat, .bin) Files that store machine-oriented data directly, not readable as text. They are handled with fwrite and fread.
Beginners often work with text files, but when dealing with image data, struct data, and similar, knowledge of binary files also becomes important.

Typical Flow of File Operations

When performing file operations in C, the basic flow is as follows.
  1. Open the file: Use the fopen function to open a file and obtain a file pointer.
  2. Read from or write to the file: Use functions such as fprintf, fscanf, fread, and fwrite to exchange data.
  3. Close the file: Close the file and release resources with the fclose function.
FILE *fp;
fp = fopen("sample.txt", "r");
if (fp != NULL) {
    // reading operations, etc.
    fclose(fp);
}
If you understand this structure, you can apply it to any file operation.

Summary: The First Step to Understanding File Operations in C

File operations in C are not just I/O; they serve as a bridge to real-world applications. By grasping file types and the basic processing flow, you’ll find it easier to understand advanced techniques you’ll learn later (such as logging, CSV handling, and using configuration files).

2. How to Open and Close Files (fopen / fclose)

File Operations Start with “fopen”

When working with files in C, the first thing you need is the fopen function. It opens a specific file and returns a “file pointer (FILE type)” for manipulating that file.
FILE *fp;
fp = fopen("example.txt", "r");
In this example, the file “example.txt” is opened in read‑only mode (r). On success, a file pointer is stored in fp; on failure, NULL is returned.

Mode Specification: Choose the Opening Method According to Use

The fopen function requires a “mode” as its second argument. This string indicates how the file will be handled, and the following types are available:
ModeDescription
“r”Open for reading only (fails if the file does not exist)
“w”Open for writing only (overwrites if the file exists, otherwise creates a new file)
“a”Open for appending (creates a new file if it does not exist)
“rb”/”wb”/”ab”Open in binary mode (commonly used on Windows)
“r+”Open for both reading and writing (no overwriting)
“w+”Open for both reading and writing (always overwrites)
“a+”Open for both reading and writing (appending only allowed)

Always Check the Return Value of fopen

When opening a file, the basic step is to verify that the return value of fopen is not NULL. There are many possible reasons for failure, including the following:
  • The file does not exist (especially in “r” mode)
  • Insufficient permissions to access the file
  • The file path is incorrect
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
    perror("Failed to open file");
    return 1;
}

Always Close with fclose When Done

After manipulating a file, you need to close the opened file using the fclose function. Failing to close a file can cause memory leaks and file corruption.
fclose(fp);
This also means “releasing resources” and is especially important when handling multiple open files.

Summary and Best Practices for fopen and fclose

  • Never forget to check for NULL with fopen Using perror when a file cannot be opened makes the cause easier to understand.
  • Follow the principle “close a file after opening it” with fclose Be sure to close files when you’re done, even before return or exit.

Practical Example: Open a Log File in Append Mode

FILE *log_fp = fopen("log.txt", "a");
if (log_fp == NULL) {
    perror("Failed to open log file");
    return 1;
}

fprintf(log_fp, "Program started\n");

fclose(log_fp);
Thus, opening in a mode makes appending to logs easy. Since it never overwrites and adds new entries each time, it is ideal for logging.
年収訴求

3. How to Write to Files (fprintf, fputs, fwrite)

File writing in C is divided into “formatted” and “binary”

C language file writing uses three functions according to the purpose.
  • fprintf: Text output with format specification (syntax similar to printf)
  • fputs: Direct text output of a string
  • fwrite: Used for writing structs or binary data
By understanding each characteristic and using them appropriately, you can implement data storage efficiently.

fprintf function: File output that feels like printf

FILE *fp = fopen("output.txt", "w");
if (fp != NULL) {
    fprintf(fp, "Name: %s\n", "Sato");
    fprintf(fp, "Age: %d\n", 28);
    fclose(fp);
}
Output:
Name: Sato
Age: 28

fputs function: Convenient for line-by-line text output

FILE *fp = fopen("log.txt", "a");
if (fp != NULL) {
    fputs("Application started\n", fp);
    fputs("User logged in\n", fp);
    fclose(fp);
}

fwrite function: Used for binary files and struct storage

struct User {
    int id;
    char name[20];
};

struct User user = {101, "Yamada"};

FILE *fp = fopen("user.dat", "wb");
if (fp != NULL) {
    fwrite(&user, sizeof(struct User), 1, fp);
    fclose(fp);
}

Understanding the differences between fwrite and fprintf

Featurefprintf / fputsfwrite
FormatTextBinary
Human readable× (generally not readable)
Struct outputUnsuitableGood
Newline handlingExplicitly requiredNot needed (binary)

Points to note when writing files

  • Always close the file with fclose after writing
  • Use fflush(fp); if you want changes to be reflected immediately
  • Error handling for failed writes can be captured with perror or ferror

Practical example: Write sensor data to a CSV file

FILE *fp = fopen("sensor.csv", "w");
if (fp != NULL) {
    fprintf(fp, "Temperature,Humidity\n");
    fprintf(fp, "%.1f,%.1f\n", 24.3, 60.2);
    fprintf(fp, "%.1f,%.1f\n", 25.1, 58.7);
    fclose(fp);
}

4. Methods for Reading from Files (fscanf, fgets, fread)

The trick is to choose the reading method that fits the purpose

When reading data from a file in C, just like writing, the functions you use differ depending on whether it’s text format or binary format.
  • fscanf: Read from a text file with a format specification
  • fgets: Read line by line as a string
  • fread: Read data from a binary file

fscanf function: Read numbers and strings by specifying a format

FILE *fp = fopen("data.txt", "r");
if (fp != NULL) {
    char name[50];
    int age;
    fscanf(fp, "%s %d", name, &age);
    printf("Name: %s, Age: %d\n", name, age);
    fclose(fp);
}

fgets function: Ideal for reading one line at a time

char buffer[256];
FILE *fp = fopen("log.txt", "r");
if (fp != NULL) {
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        printf("%s", buffer);
    }
    fclose(fp);
}

fread function: Bulk reading of binary data or structures

struct User {
    int id;
    char name[20];
};

struct User user;

FILE *fp = fopen("user.dat", "rb");
if (fp != NULL) {
    fread(&user, sizeof(struct User), 1, fp);
    printf("ID: %d, Name: %s\n", user.id, user.name);
    fclose(fp);
}

Common considerations when reading

  • Detecting end of file is checked via feof() or the return value of fgets/fscanf
  • Handling of newlines and whitespace must be done properly, otherwise data can become misaligned
  • Error handling consider using ferror() or perror()

Practical example: Reading and parsing a CSV file line by line

char line[100];
FILE *fp = fopen("sensor.csv", "r");
if (fp != NULL) {
    while (fgets(line, sizeof(line), fp)) {
        char temp[10], humid[10];
        sscanf(line, "%[^,],%s", temp, humid);
        printf("Temperature: %s°C Humidity: %s%%\n", temp, humid);
    }
    fclose(fp);
}

Summary: Choose between fscanf, fgets, and fread according to your purpose

FunctionSuitable UseFormatFeatures
fscanfReading numbers and stringsRequires a fixed formatSensitive to format
fgetsLine-by-line string readingFree formatIncludes newline
freadBinary data or structuresNo specific format requiredComplementary to writing

5. Error handling and debugging during file operations

Why is error handling important?

C language file operations are characterized by a large number of operations that can fail. For example, the following situations can occur:
  • File does not exist
  • No read permission
  • Write failure due to insufficient disk space
  • Read errors caused by format errors

fopen returns NULL when it fails

FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
    perror("Failed to open file");
    return 1;
}

perror function: intuitive error message display

perror("Error occurred");
Example output:
Error occurred: No such file or directory

strerror function: obtain error message as a string

#include <string.h>
#include <errno.h>

fprintf(stderr, "Error details: %sn", strerror(errno));

ferror function: check if an I/O stream has encountered an error

if (ferror(fp)) {
    fprintf(stderr, "An error occurred during file operationn");
}

feof function: check if end of file has been reached

while (!feof(fp)) {
    fgets(buffer, sizeof(buffer), fp);
    // ...
}
Safer approach:
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
    // reading process
}

Common file operation errors and their causes

SymptomPrimary causeCountermeasure
fopen returns NULLFile does not exist, insufficient permissions, incorrect pathCheck details with perror
Writes not reflectedUnwritten due to bufferingUse fflush or fclose
Data is corruptedFormat mismatch, binary read/write errorsVerify struct sizes and order
Reading stops midwayMistakes in newline or EOF handlingControl with fgets and return values

Summary: Robust checks are essential for safe file operations

  • fopen return value check (NULL test)
  • Explicit cause using perror or strerror
  • State checks with ferror and feof
Combine these to implement safe and reliable file handling.

6. Practical Example | Programs Using File Operations in C

Deepen Your Understanding Not Just with Theory, but with Real-World Usage

So far, we have covered the basics to advanced techniques of file operations in C. In this section, we will translate the knowledge you have learned into a usable form through practical sample code for file operations.

Output to Log File: Recording Application Activity

#include <stdio.h>
#include <time.h>

void write_log(const char *message) {
    FILE *fp = fopen("app.log", "a");
    if (fp != NULL) {
        time_t now = time(NULL);
        fprintf(fp, "[%s] %sn", ctime(&now), message);
        fclose(fp);
    }
}
int main() {
    write_log("Application started");
    write_log("Processing completed successfully");
    return 0;
}

Writing Data to CSV Files: Storing Data in Tabular Form

#include <stdio.h>

int main() {
    FILE *fp = fopen("data.csv", "w");
    if (fp != NULL) {
        fprintf(fp, "ID,Name,Scoren");
        fprintf(fp, "1,Tanaka,88n");
        fprintf(fp, "2,Yamada,92n");
        fclose(fp);
    }
    return 0;
}

Reading Configuration Files (.conf): Flexible Configuration Management

config.conf:
username=guest
timeout=30
#include <stdio.h>
#include <string.h>

int main() {
    FILE *fp = fopen("config.conf", "r");
    char line[100];
    if (fp != NULL) {
        while (fgets(line, sizeof(line), fp)) {
            char key[50], value[50];
            if (sscanf(line, "%[^=]=%s", key, value) == 2) {
                printf("Setting: %s, Value: %sn", key, value);
            }
        }
        fclose(fp);
    }
    return 0;
}

Example of Saving Multiple Data Structures to Binary

#include <stdio.h>

struct User {
    int id;
    char name[20];
};

int main() {
    struct User users[2] = {
        {1, "Suzuki"},
        {2, "Kato"}
    };

    FILE *fp = fopen("users.dat", "wb");
    if (fp != NULL) {
        fwrite(users, sizeof(struct User), 2, fp);
        fclose(fp);
    }
    return 0;
}

Summary: File Operations Are a Versatile Tool for Any Situation

  • Log: For operation verification and error tracing
  • CSV: For data exchange with external tools
  • Configuration File: For external manipulation by users
  • Binary Storage: For fast and space-efficient data processing

7. Frequently Asked Questions (FAQ) about C Language File Operations

Solve All Common Pitfalls for Beginners!

Here we summarize common questions and practical issues you may encounter in a Q&A format.

Q1. Why can’t fopen open the file?

A1. The following reasons are possible:
  • The file does not exist
  • The path is incorrect
  • Insufficient access permissions
  • The file is locked
Solution:
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
    perror("Failed to open file");
}

Q2. Why doesn’t the written content appear in the file?

A2. It may not be written immediately due to buffering. Fix:
fprintf(fp, "Test data\n");
fflush(fp);  // or fclose(fp);

Q3. What is the difference between binary files and text files?

ItemText FileBinary File
ContentReadable stringsNon-readable data
SizeMay be largerSmaller and faster
Functions usedfprintf, fputsfwrite

Q4. Why does reading stop partway through a file?

A4. There may be issues with EOF handling or read conditions. Safe method:
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
    // process
}

Q5. Can character encoding differences cause garbled text?

A5. Yes. Differences such as between Shift_JIS and UTF-8 can cause garbled characters across different OSes. Solution:
  • Explicitly unify the character encoding in editors and compiler options

Q6. Is it safe to open the same file multiple times with fopen?

A6. It’s possible if opened read‑only, but caution is needed when writing. Consider lock mechanisms, etc.

Q7. How to write errors to a log file instead of standard output?

A7.
FILE *log = fopen("error.log", "a");
if (log != NULL) {
    fprintf(log, "An error occurred: %s\n", strerror(errno));
    fclose(log);
}

FAQ: Overcome Pitfalls and Solidify Your Learning

The FAQs presented here gather points that beginners to intermediate users commonly stumble on when handling files in C.

8. Summary | Master C Language File I/O to Expand Your Program’s Capabilities

Reviewing File Operations in C

In this article, we have systematically explained file operations in C, from basics to advanced topics. Specifically, we covered the following content.
  • File types (text/binary) and their characteristics
  • Opening and closing files with fopen and fclose
  • Writing methods using fprintf, fputs, and fwrite
  • Reading methods using fscanf, fgets, and fread
  • Basics of error handling and troubleshooting
  • Practical examples such as logging, CSV saving, and reading configuration files
  • FAQ summarizing common pitfalls for beginners

File Operations as a Bridge to the Real World

File I/O is not just an internal program process; it serves as an interface with users and other systems. Logging, loading configurations, data storage, and other practical uses rely on this essential functionality.

Next Learning Steps

If you have mastered this material, you may want to tackle the following advanced topics.
  • Saving arrays of structs or list structures to files
  • Accelerating text processing (e.g., optimizing buffer sizes)
  • Implementing file locking and exclusive control
  • Integrating with compressed files (gz, zip) using external libraries
By mastering file operations in C, your programs will evolve into practical applications. Use this article as a reference and actively implement and test the concepts.