Understanding C Language: Comprehensive Guide to File Handling

Hello, friends! I am Shangqiu Bofeng~ Today, let’s step into the wonderful world of C language. This article mainly introduces a comprehensive guide to file handling in C language. The examples in this article are described in great detail, providing valuable reference for your study or work. Friends who need it can take a look!

1. Basic Concepts of Files

In C language, a file is a collection of data stored on external media (such as a disk). Files can be divided into text files and binary files.

  • Text Files: Text files are files based on character encoding, commonly seen in ASCII or UTF-8 encoding. In text files, each character has a corresponding character code and can be viewed and edited directly through a text editor. For example, a text file containing the number 123 actually stores the ASCII values of characters '1', '2', and '3' in memory (which are 49, 50, and 51 respectively).

  • Binary Files: Binary files store the binary representation of data. They are not stored in character encoding but directly store the binary bits of the data. For example, an integer 123 in a binary file may be stored in a 4-byte (assuming a 32-bit integer) binary form 00000000 00000000 00000000 01111011. Such files usually cannot be meaningfully viewed and edited directly through text editors, but they may offer higher efficiency in storage and reading.

2. File Pointers

In C language, files are operated on through file pointers. A file pointer is a pointer to a FILE type structure. The FILE structure contains various information about the file, such as the current position in the file, buffer information, etc.

To use a file pointer, you need to include the <stdio.h> header file. The general form of defining a file pointer is: FILE *fp;, where fp is the file pointer variable we defined.

3. Opening and Closing Files

1. Opening Files

  • • Function Prototype: FILE *fopen(const char *filename, const char *mode);

  • Parameter Explanation:

    • filename: The name of the file to be opened, which can include the file path. For example, "data.txt" is a file in the current directory, while "C:/myfiles/test.dat" is a file in an absolute path.

    • mode: The file opening mode, common modes include:

      • "r": Opens the text file in read-only mode. If the file does not exist, opening fails.

      • "w": Opens the text file in write-only mode. If the file exists, the content will be cleared; if it does not exist, a new file will be created.

      • "a": Opens the text file in append mode. If the file exists, content will be added at the end; if it does not exist, a new file will be created.

      • "rb", "wb", "ab": Read-only, write-only, and append modes for binary files, respectively.

      • "r+", "w+", "a+": Opens the text file in read-write mode, with similar functions as mentioned above.

      • "rb+", "wb+", "ab+": Opens the binary file in read-write mode.

  • Example Code:

#include <stdio.h>
int main()
{
    FILE *fp;
    fp = fopen("test.txt", "w");
    if (fp == NULL)
    {
        perror("Error opening file");
        return 1;
    }
    // File operation code will be introduced later
    fclose(fp);
    return 0;
}

In this example, we first attempt to open the test.txt file in write-only mode. If fp is NULL, it indicates that opening the file failed, and the error message is output using the perror function.

2. Closing Files

  • • Function Prototype: int fclose(FILE *stream);

  • Function Explanation: Closes the file that was previously opened using the fopen function. Closing files is very important as it ensures that data in the buffer is correctly written to the file and releases resources related to the file.

  • Return Value: Returns 0 if the file is successfully closed; if an error occurs, returns EOF (-1).

4. File Read and Write Operations

1. Character Read and Write

  • fgetc Function

    • • Function Prototype: int fgetc(FILE *stream);

    • Function Explanation: Reads a character from the specified file stream stream. The read character is returned as int type, as EOF (the end-of-file marker) also needs to be represented by a special value, which is typically -1.

    • Example Code:

#include <stdio.h>
int main()
{
    FILE *fp;
    int ch;
    fp = fopen("test.txt", "r");
    if (fp == NULL)
    {
        perror("Error opening file");
        return 1;
    }
    ch = fgetc(fp);
    while (ch != EOF)
    {
        putchar(ch);
        ch = fgetc(fp);
    }
    fclose(fp);
    return 0;
}

In this example, we read the content of the test.txt file character by character and output it to the console using the putchar function until we reach EOF.

  • fputc Function

    • • Function Prototype: int fputc(int c, FILE *stream);

    • Function Explanation: Writes the character c to the specified file stream stream. If the write is successful, the written character is returned; if an error occurs, EOF is returned.

    • Example Code:

#include <stdio.h>
int main()
{
    FILE *fp;
    char ch = 'A';
    fp = fopen("test.txt", "w");
    if (fp == NULL)
    {
        perror("Error opening file");
        return 1;
    }
    fputc(ch, fp);
    fclose(fp);
    return 0;
}

In this example, we write the character 'A' to the test.txt file.

2. String Read and Write

  • fgets Function

    • • Function Prototype: char *fgets(char *s, int size, FILE *stream);

    • Function Explanation: Reads up to size - 1 characters from the file stream stream and stores them in the character array s. The read character sequence is terminated with '\0', forming a string. If a newline character '\n' or the end-of-file marker EOF is encountered before reading size - 1 characters, reading ends.

    • Example Code:

#include <stdio.h>
int main()
{
    FILE *fp;
    char str[100];
    fp = fopen("test.txt", "r");
    if (fp == NULL)
    {
        perror("Error opening file");
        return 1;
    }
    fgets(str, 100, fp);
    printf("%s", str);
    fclose(fp);
    return 0;
}

In this example, we read up to 99 characters (to leave space for '\0') from the test.txt file into the str array and then output it to the console.

  • fputs Function

    • • Function Prototype: int fputs(const char *s, FILE *stream);

    • Function Explanation: Writes the string s to the file stream stream. No newline character '\n' is automatically added during writing. If the write is successful, a non-negative integer is returned; if an error occurs, EOF is returned.

    • Example Code:

#include <stdio.h>
int main()
{
    FILE *fp;
    char str[] = "Hello, World!";
    fp = fopen("test.txt", "w");
    if (fp == NULL)
    {
        perror("Error opening file");
        return 1;
    }
    fputs(str, fp);
    fclose(fp);
    return 0;
}

In this example, we write the string "Hello, World!" to the test.txt file.

3. Formatted Read and Write

  • fscanf Function

    • • Function Prototype: int fscanf(FILE *stream, const char *format,...);

    • Function Explanation: Reads data from the file stream stream according to the specified format format and stores the read data into the corresponding variables. Its usage is similar to the scanf function, except that the data source is a file instead of standard input.

    • Example Code:

#include <stdio.h>
int main()
{
    FILE *fp;
    int num;
    char str[100];
    fp = fopen("test.txt", "r");
    if (fp == NULL)
    {
        perror("Error opening file");
        return 1;
    }
    fscanf(fp, "%d %s", &num, str);
    printf("Number: %d, String: %s", num, str);
    fclose(fp);
    return 0;
}

In this example, assuming that the test.txt file contains an integer and a string separated by a space, we read these two pieces of data using the fscanf function and output them.

  • fprintf Function

    • • Function Prototype: int fprintf(FILE *stream, const char *format,...);

    • Function Explanation: Writes formatted data according to the format format to the file stream stream. Its usage is similar to the printf function, except that the output target is a file instead of standard output.

    • Example Code:

#include <stdio.h>
int main()
{
    FILE *fp;
    int num = 10;
    char str[] = "Test";
    fp = fopen("test.txt", "w");
    if (fp == NULL)
    {
        perror("Error opening file");
        return 1;
    }
    fprintf(fp, "%d %s", num, str);
    fclose(fp);
    return 0;
}

In this example, we write the integer 10 and the string "Test" to the test.txt file in the specified format.

4. Binary File Read and Write

  • fread Function

    • • Function Prototype: size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

    • Function Explanation: Reads nmemb blocks of data, each size bytes in size, from the file stream stream and stores them in the memory space pointed to by ptr. The return value is the actual number of elements read (not the byte count). If the number of bytes read is less than nmemb * size, it may be due to reaching the end of the file or an error occurring.

    • Example Code:

#include <stdio.h>
#define ARRAY_SIZE 10
int main()
{
    FILE *fp;
    int array[ARRAY_SIZE];
    size_t num_read;
    fp = fopen("data.bin", "rb");
    if (fp == NULL)
    {
        perror("Error opening file");
        return 1;
    }
    num_read = fread(array, sizeof(int), ARRAY_SIZE, fp);
    fclose(fp);
    for (size_t i = 0; i < num_read; i++)
    {
        printf("%d ", array[i]);
    }
    return 0;
}

In this example, we read 10 integers from the binary file data.bin into the array array and then output the read integers.

  • fwrite Function

    • • Function Prototype: size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

    • Function Explanation: Writes nmemb blocks of data, each size bytes in size, from the memory space pointed to by ptr to the file stream stream. The return value is the actual number of elements written.

    • Example Code:

#include <stdio.h>
#define ARRAY_SIZE 10
int main()
{
    FILE *fp;
    int array[ARRAY_SIZE] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    size_t num_written;
    fp = fopen("data.bin", "wb");
    if (fp == NULL)
    {
        perror("Error opening file");
        return 1;
    }
    num_written = fwrite(array, sizeof(int), ARRAY_SIZE, fp);
    fclose(fp);
    return 0;
}

In this example, we write 10 integers from the array array into the binary file data.bin.

5. File Positioning

  • ftell Function

    • • Function Prototype: long int ftell(FILE *stream);

    • Function Explanation: Returns the current position of the file stream stream, which is the offset from the beginning of the file, in bytes. If an error occurs, it returns -1L.

    • Example Code:

#include <stdio.h>
int main()
{
    FILE *fp;
    long int pos;
    fp = fopen("test.txt", "r");
    if (fp == NULL)
    {
        perror("Error opening file");
        return 1;
    }
    // Read some content
    fgetc(fp);
    pos = ftell(fp);
    printf("Current position: %ld", pos);
    fclose(fp);
    return 0;
}

In this example, after opening the test.txt file and reading a character, we use the ftell function to get the current file position and output it.

  • fseek Function

    • • Function Prototype: int fseek(FILE *stream, long int offset, int whence);

    • Parameter Explanation:

      • stream: The file stream.

      • offset: The offset, in bytes.

      • whence: Specifies the starting position of the offset, with the following possible values:

        • SEEK_SET: Offset from the beginning of the file, offset must be non-negative.

        • SEEK_CUR: Offset from the current position.

        • SEEK_END: Offset from the end of the file, offset is usually negative, indicating an offset towards the beginning of the file.

    • Function Explanation: Moves the position pointer of the file stream stream to the specified location. Returns 0 if successful; returns -1 if an error occurs.

    • Example Code:

#include <stdio.h>
int main()
{
    FILE *fp;
    fp = fopen("test.txt", "r");
    if (fp == NULL)
    {
        perror("Error opening file");
        return 1;
    }
    fseek(fp, 5, SEEK_SET);
    // Start reading content from the new position
    // ......
    fclose(fp);
    return 0;
}

In this example, we use the fseek function to move the file pointer 5 bytes from the beginning of the file, and then we can start reading the file content from this new position.

  • rewind Function

    • • Function Prototype: void rewind(FILE *stream);

    • Function Explanation: Resets the position pointer of the file stream stream to the beginning of the file. This is equivalent to fseek(stream, 0, SEEK_SET);.

    • Example Code:

#include <stdio.h>
int main()
{
    FILE *fp;
    fp = fopen("test.txt", "r");
    if (fp == NULL)
    {
        perror("Error opening file");
        return 1;
    }
    // Read some content
    // ......
    rewind(fp);
    // Read content again from the beginning
    // ......
    fclose(fp);
    return 0;
}

In this example, after reading part of the file content, we use the rewind function to reset the file pointer to the beginning of the file so we can read the file content again.

Leave a Comment