C File Handling Explained: Read, Write, Append, and Manage Files

File handling allows C programs to store and retrieve data from files. Instead of keeping information only in memory while a program is running, files make it possible to preserve data between program executions.

What is File Handling in C?

C provides file-handling functions through the stdio.h header. A FILE pointer represents an open stream and is used with functions for reading, writing, and managing files.

C
#include <stdio.h>

int main(void)
{
    FILE *file;

    file = fopen("data.txt", "r");

    if (file == NULL)
    {
        printf("Could not open file.\n");
        return 1;
    }

    fclose(file);

    return 0;
}

Opening a File with fopen

The fopen function opens a file and returns a FILE pointer. If the operation fails, it returns NULL.

C
FILE *file = fopen("data.txt", "r");

if (file == NULL)
{
    printf("Failed to open file.\n");
    return 1;
}

File Opening Modes

ModePurpose
rOpen an existing file for reading
wOpen for writing and create or truncate the file
aOpen for writing at the end of the file
r+Open an existing file for reading and writing
w+Open for reading and writing, creating or truncating the file
a+Open for reading and writing with writes at the end

Writing Text with fprintf

fprintf writes formatted text to a file in a way similar to printf writing to standard output.

C
#include <stdio.h>

int main(void)
{
    FILE *file = fopen("data.txt", "w");

    if (file == NULL)
    {
        return 1;
    }

    fprintf(file, "Name: %s\n", "Alex");
    fprintf(file, "Age: %d\n", 25);
    fprintf(file, "Score: %.2f\n", 91.5);

    fclose(file);

    return 0;
}

Writing Text with fputs

fputs writes a string to a file stream.

C
#include <stdio.h>

int main(void)
{
    FILE *file = fopen("message.txt", "w");

    if (file == NULL)
    {
        return 1;
    }

    fputs("Hello from C!\n", file);
    fputs("File handling is useful.\n", file);

    fclose(file);

    return 0;
}

Writing a Character with fputc

fputc writes a single character to a file stream.

C
#include <stdio.h>

int main(void)
{
    FILE *file = fopen("letters.txt", "w");

    if (file == NULL)
    {
        return 1;
    }

    fputc('A', file);
    fputc('B', file);
    fputc('C', file);

    fclose(file);

    return 0;
}

Reading Text with fgets

fgets reads a line or a portion of a line from a file into a character array.

C
#include <stdio.h>

int main(void)
{
    FILE *file = fopen("data.txt", "r");

    if (file == NULL)
    {
        return 1;
    }

    char line[256];

    while (fgets(line, sizeof line, file) != NULL)
    {
        printf("%s", line);
    }

    fclose(file);

    return 0;
}

Reading Characters with fgetc

fgetc reads one character at a time and returns EOF when the end of the input stream is reached or an input error occurs.

C
#include <stdio.h>

int main(void)
{
    FILE *file = fopen("data.txt", "r");

    if (file == NULL)
    {
        return 1;
    }

    int ch;

    while ((ch = fgetc(file)) != EOF)
    {
        putchar(ch);
    }

    fclose(file);

    return 0;
}

Formatted Input with fscanf

fscanf can read formatted data from a file stream. It is useful when the file contains predictable structured input.

C
#include <stdio.h>

int main(void)
{
    FILE *file = fopen("numbers.txt", "r");

    if (file == NULL)
    {
        return 1;
    }

    int a;
    int b;

    if (fscanf(file, "%d %d", &a, &b) == 2)
    {
        printf("Sum: %d\n", a + b);
    }

    fclose(file);

    return 0;
}

Appending Data to a File

The a mode writes new data at the end of an existing file without removing its previous contents.

C
#include <stdio.h>

int main(void)
{
    FILE *file = fopen("log.txt", "a");

    if (file == NULL)
    {
        return 1;
    }

    fprintf(file, "New log entry\n");

    fclose(file);

    return 0;
}

Binary Files

C can also read and write binary data using fread and fwrite. Binary files store raw bytes rather than formatted text.

C
#include <stdio.h>

int main(void)
{
    int numbers[] = {10, 20, 30, 40};

    FILE *file = fopen("numbers.bin", "wb");

    if (file == NULL)
    {
        return 1;
    }

    size_t count = sizeof numbers / sizeof numbers[0];

    fwrite(numbers, sizeof numbers[0], count, file);

    fclose(file);

    return 0;
}

Reading Binary Data with fread

C
#include <stdio.h>

int main(void)
{
    int numbers[4];

    FILE *file = fopen("numbers.bin", "rb");

    if (file == NULL)
    {
        return 1;
    }

    size_t count = fread(
        numbers,
        sizeof numbers[0],
        4,
        file
    );

    for (size_t i = 0; i < count; i++)
    {
        printf("%d\n", numbers[i]);
    }

    fclose(file);

    return 0;
}

Closing a File with fclose

fclose closes an open file stream and flushes buffered output associated with the stream.

C
FILE *file = fopen("data.txt", "w");

if (file != NULL)
{
    fputs("Hello\n", file);
    fclose(file);
}

Checking for End of File

EOF is a special negative integer value used by input functions such as fgetc to indicate that no more characters can be read or that an input error occurred. feof and ferror can help distinguish the condition after an input operation.

C
int ch;

while ((ch = fgetc(file)) != EOF)
{
    putchar(ch);
}

if (ferror(file))
{
    printf("A file error occurred.\n");
}

File Position Functions

C provides functions such as fseek, ftell, and rewind for controlling and inspecting the current position in a file stream.

C
FILE *file = fopen("data.txt", "r");

if (file == NULL)
{
    return 1;
}

fseek(file, 0, SEEK_END);

long size = ftell(file);

printf("File position: %ld\n", size);

rewind(file);

fclose(file);

Renaming and Removing Files

The standard C library provides rename and remove for basic file management operations.

C
#include <stdio.h>

int main(void)
{
    if (rename("old.txt", "new.txt") != 0)
    {
        perror("rename");
    }

    if (remove("temporary.txt") != 0)
    {
        perror("remove");
    }

    return 0;
}

Text Files vs Binary Files

FeatureText FileBinary File
ContentHuman-readable charactersRaw bytes
Common Functionsfgets, fputs, fprintf, fscanffread, fwrite
Typical UseLogs and configurationStructured binary data
ReadabilityUsually readable with a text editorUsually not directly readable

Common File Handling Mistakes

  • Failing to check whether fopen returned NULL
  • Forgetting to close an opened file
  • Using the wrong file mode
  • Overwriting a file accidentally with w mode
  • Using an inappropriate buffer size
  • Ignoring read and write errors
  • Treating binary data as portable across all systems without considering representation

File Handling Best Practices

  • Always check whether a file opened successfully
  • Close files when they are no longer needed
  • Choose the correct mode for the operation
  • Check return values from important file operations
  • Use fgets for safer line-oriented text input
  • Use binary modes when working with binary data where required by the platform
  • Keep file paths and permissions under control

Real-World Applications

  • Log files
  • Configuration files
  • Data storage
  • Report generation
  • CSV and text processing
  • Binary data processing
  • Backup utilities

Practice Exercises

  • Create a file and write five lines to it
  • Read a text file line by line
  • Count characters in a file
  • Append log entries to a file
  • Copy one file into another
  • Store integers in a binary file
  • Read a binary file and calculate the sum of its values

Conclusion

File handling gives C programs persistent storage and access to external data. By learning fopen, fclose, fgets, fputs, fprintf, fscanf, fread, fwrite, and file-position functions, you can build programs that reliably work with both text and binary files.

Note: Note: File operations can fail for many reasons, including missing files, permissions, invalid paths, and storage problems. Always check important return values instead of assuming an operation succeeded.