《小菜狗 C 语言入门 + 进阶笔记》(42)文件进阶操作 - 读写文件【重要,后面牛马的时候也经常用】


《小菜狗 C 语言入门 + 进阶笔记》目录:《小菜狗 C 语言入门 + 进阶笔记》(0)简介

1、以字符形式读写文件

在进行文件操作的时候,我们需要向文件中写入单个字符,从文件中读取单个字符,这时就可以使用 fgetc 和 fputc 来完成任务。

1.1、 fgetc 函数

函数定义:

int fgetc(FILE* stream);

功能:

函数用于从指定的文件流中读取单个字符,并将其返回为⼀个无符号字符。

参数:

指向 FILE 类型结构体的指针,指定了要读取字符的文件流。

返回值:

返回读取的字符,返回的是字符的 ASCII 码值。如果到达文件末尾或者发生错误,返回 EOF ,即 (-1) 。

使用注意事项:

  • 需要包含 <stdio.h> 头文件。
  • 在使用 fgetc() 之前,需要确保文件已经以可读方式打开
  • 返回的字符是以 unsigned char 形式返回,但是它会被转换为 int 类型以⽀持特殊值 EOF 。
  • 文件指针会随着每次读取的调用而向前移动。

代码举例:

#include <stdio.h>
int main()
{
    FILE *fp;
    int c;

    // (1)打开文件
    fp = fopen("test.txt", "r");

    // (2)检查文件是否成功打开
    if (fp == NULL)
    {
        perror("fopen");
        return -1;
    }

    // (3)读取文件中的每个字符
    while ((c = fgetc(fp)) != EOF)
    {
        printf("%c", c);
    }

    // (4)关闭文件
    fclose(fp);
    return 0;
}
1.2、 fputc 函数

函数定义:

int fputc(int c, FILE* stream);

功能:

函数用于向指定的文件流中写入⼀个字符。

参数:

  • c :要写入的字符,以整数形式给出。
  • stream :指向 FILE 类型结构体的指针,指定了要写入字符的流。

返回值:

如果成功写入字符,则返回写入的字符,以无符号字符表⽰。如果发生错误,返回 EOF ,即 (-1)。

使用注意事项:

  • 需要包含 <stdio.h> 头文件。
  • 在使用 fputc() 之前,需要确保文件已经以可写方式打开。
  • 文件指针会随着每次写入的调用而向前移动。

代码举例:

#include <stdio.h>
int main()
{
    FILE *fp;
    int c;

    // (1)打开文件
    fp = fopen("test.txt", "w");

    // (2)检查文件是否成功打开
    if (fp == NULL)
    {
        perror("fopen");
        return -1;
    }

    // (3)写入字符到文件中
    for (c = 'A'; c <= 'Z'; ++c)
    {
        if (fputc(c, fp) == EOF)
        {
            perror("Error writing to file");
            return -1;
        }
    }

    // (4)关闭文件
    fclose(fp);
    return 0;
}

2、以字符串形式读写文件

在进行文件操作的时候,我们需要向文件中写入⼀行字符,从文件中读取⼀行字符,这时就可以使用 fgets 和 fputs 来完成任务。

2.1、 fgets 函数

函数定义:

char* fgets(char* str, int n, FILE * stream); 

功能:

函数用于从指定的文件流中读取⼀行文本,并将其存储为⼀个字符串。

参数:

  • str :指向⼀个字符数组的指针,用于存储读取的文本内容。该数组必须⾜够大以容纳最大⻓度为 n-1 的字符串,因为函数会在末尾添加⼀个 \0 终止符。
  • n :要读取的最大字符数,包括末尾的 \0 终止符。如果读取的行超过 n-1 个字符,则剩余的字符会被截断。
  • stream :指向 FILE 类型结构体的指针,指定了要读取的文件流。

返回值:

char * :如果成功读取到⼀行文本,则返回 str 参数的值。如果到达文件末尾或者发生错误,则返回 NULL 。

使用注意事项:

  • 需要包含 <stdio.h> 头文件。
  • 在使用 fgets() 之前,需要确保文件已经以可读方式打开。
  • 函数会将包括换行符在内的整行文本读取到 str 指向的缓冲区中,但会在末尾添加 \0 终止符。
  • 如果⼀行文本的字符数不超过 n-1 ,则整行文本以及末尾的换行符都会被读取并存储。
  • 如果⼀行文本的字符数超过 n-1 ,则前 n-1 个字符会被读取并存储,剩余字符会被截断。
  • 如果文件中没有更多的行可读,则 fgets() 返回 NULL。

代码举例:

#include <stdio.h>
int main()
{
    FILE *fp;
    char buffer[255];

    fp = fopen("test.txt", "r");

    if (fp == NULL) {
        perror("fopen");
        return -1;
    }
    // 读取文件中的每⼀行并打印
    while (fgets(buffer, 255, fp) != NULL) {
        printf("%s", buffer);
    }

    fclose(fp);
    return 0;
}
2.2、 fputs 函数

函数定义:

int fputs(const char *str, FILE *stream);

功能:

函数用于将⼀个字符串写入到指定的文件流中,直到遇到 \0 为止。

参数:

• str :要写入的字符串

• stream :指向 FILE 类型结构体的指针,指定了要写入字符串的文件流。

返回值:

int :如果成功写入字符串,则返回⾮负值(通常为 0)。如果发生错误,返回 EOF ,即 (-1) 。

使用注意事项:

  • 需要包含 <stdio.h> 头文件。
  • 在使用 fputs() 之前,需要确保文件已经以可写方式打开。
  • fputs() 写入的字符串不会自动添加换行符,需要⼿动添加 \n 如果需要。

代码举例:

#include <stdio.h>
int main()
{
    FILE *fp;

    fp = fopen("test.txt", "w");

    if (fp == NULL) {
        perror("Error opening file");
        return -1;
    }

    // 写入字符串到文件中
    if (fputs("Hello, world!", fp) == EOF) {
        perror("fputs");
        return -1;
    }

    fclose(fp);
    return 0;
}

3、以数据块形式读写文件

3.1、 fwrite 函数

函数定义:

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

功能:

函数用于将数据块写入文件流中,是以 2 进制的形式写入的。

参数:

  • ptr :指向要写入的数据块的指针。
  • size :要写入的每个数据项的大小(以字节为单位)。
  • nmemb :要写入的数据项的数量。
  • stream :指向 FILE 类型结构体的指针,指定了要写入数据的文件流。

返回值:

返回实际写入的数据项数量。如果发生错误,则返回值可能小于 nmemb 。

使用注意事项:

  • 需要包含 <stdio.h> 头文件。
  • 在使用 fwrite() 之前,需要确保文件已经以二进制可写方式打开。
  • fwrite() 通常用于二进制数据的写入,如果写入文本数据,请谨慎处理换行符和编码等问题。

代码举例:

假设要将⼀组整数写入到文件"data.bin"中:

#include <stdio.h>
int main() {
    FILE *fp;
    int data[] = {1, 2, 3, 4, 5};

    fp = fopen("data.bin", "wb");

    if (fp == NULL) {
        perror("fopen");
        return -1;
    }
    // 将数据写入文件
    if (fwrite(data, sizeof(int), 5, fp) != 5) {
        perror("fwrite");
        return -1;
    }

    fclose(fp);
    pf = NULL;
    return 0;
}
3.2、 fread 函数

函数定义:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

功能:

函数用于从文件中读取数据块,并将其存储到内存缓冲区中。

参数:

  • ptr :指向内存区域的指针,用于存储从文件中读取的数据。
  • size :要读取的每个数据块的大小(以字节为单位)。
  • nmemb :要读取的数据块的数量。
  • stream :指向 FILE 类型结构体的指针,指定了要从中读取数据的文件流。

返回值:

返回实际读取的数据块数量。

使用注意事项:

  • 需要包含 <stdio.h> 头文件。
  • 在使用 fread() 之前,需要确保文件已经以二进制可读方式打开。
  • ptr 指向的内存区域必须⾜够大,以便存储指定数量和大小的数据块。
  • 如果 fread() 成功读取了指定数量的数据块,则返回值等于 nmemb ;如果读取数量少于 nmemb ,则可能已经到达文件结尾或者发生了错误。
  • 在二进制文件读取时, fread() 是常用的函数,但对于文本文件读取,通常使用 fgets() 或 fscanf() 。

代码举例:

假设有⼀个二进制文件"data.bin",包含⼀些整数数据,我们将使用 fread() 函数读取这些数据:

#include <stdio.h>
int main()
{
    FILE *fp;
    int data[5]; // 假设文件中包含 5 个整数数据

    fp = fopen("data.bin", "rb");

    if (fp == NULL) {
        perror("fopen");
        return -1;
    }
    // 从文件中读取整数数据块
    size_t num_read = fread(data, sizeof(int), 5, fp);
    // 检查读取是否成功
    if (num_read != 5) {
        if (feof(fp))
            printf("Reached end of file\n");
            else if (ferror(fp))
            printf("Error reading file\n");
        } else {
            // 输出读取的数据
            for (int i = 0; i < 5; i++) {
                printf("Data[%d]: %d\n", i, data[i]);
        }
    }

    fclose(fp);
    return 0;
}

4、格式化读写文件

如果我们需要向文件中写入和读取的不仅仅是字符,而是有其他类型的文本数据,那就得考虑 fscanf 函数和 fprintf 函数了。

4.1、 fscanf 函数

函数定义:

int fscanf(FILE *stream, const char *format, ...); 

功能:

函数用于从指定流中读取格式化输入,并根据指定的格式化字符串将输入数据解析为相应的数据类型。

参数:

  • stream :指向 FILE 类型结构体的指针,指定了要读取的文件流。
  • format :格式化字符串,指定了要读取的输入数据的格式,类似于 scanf() 中的格式化字符串。
  • … :可变数量的参数,根据 format 字符串中指定的格式,用于接收解析后的数据。

返回值:

int :返回成功读取和匹配的参数个数。如果达到文件结尾或者发生读取错误,则返回 EOF ,即(-1) 。

使用注意事项:

  • 需要包含 <stdio.h> 头文件。
  • 在使用 fscanf() 之前,需要确保文件已经以可读方式打开。
  • format 字符串中可以包含各种格式标识符,如 %d (整数)、%f (浮点数)、%s (字符串)等。
  • 与 scanf() 不同, fscanf() 是从指定的流中读取数据,可以是标准输入流,也可以是文件流。

代码举例:

假设有⼀个包含⼀些数据的文件"data.txt",内容如下:

John 25 1.7
Emily 23 1.6
zhangsan 28 2.1

代码如下:

#include <stdio.h>
int main() {
    FILE *fp;
    char name[20];
    int age;
    float height;
    
    fp = fopen("data.txt", "r");
    
    if (fp == NULL) {
        perror("Error opening file");
        return -1;
    }
    // 从文件中读取数据
    while (fscanf(fp, "%s %d %f", name, &age, &height) != EOF) {
        printf("Name: %s, Age: %d, Height: %.1f\n", name, age, height);
    }
    
    fclose(fp);
    return 0;
}
4.2、 fprintf 函数

函数定义:

int fprintf(FILE *stream, const char *format, ...); 

功能:

fprintf() 函数用于将格式化数据写入到指定的流中。

参数:

  • stream :指向 FILE 类型结构体的指针,指定了要写入的流。
  • format :格式化字符串,指定了要写入的输出数据的格式,类似于 printf() 中的格式化字符串。
  • … :可变数量的参数,根据 format 字符串中指定的格式,用于提供要写入的数据。

返回值:

int :返回写入的字符数。如果发生错误,返回负值。

使用注意事项:

  • 需要包含 <stdio.h> 头文件。
  • 在使用 fprintf() 之前,需要确保文件已经以可写方式打开。
  • format 字符串中可以包含各种格式标识符,如 %d (整数)、 %f (浮点数)、 %s (字符串)等。
  • fprintf() 将输出写入到指定的件流中,可以是标准输出流,也可以是文件流。

代码举例:

#include <stdio.h>
int main()
{
    FILE *fp;
    int num1 = 10;
    float num2 = 3.14;
    char str[] = "Hello, world!";

    fp = fopen("output.txt", "w");

    if (fp == NULL) {
        perror("Error opening file");
        return -1;
    }
    // 将数据写入文件
    fprintf(fp, "Integer: %d, Float: %.2f, String: %s\n", num1, num2, str);

    fclose(fp);
    return 0;
}

每日一更!

公众号、优快云等博客:小菜狗编程笔记

谢谢点赞关注哈!目前在飞书持续优化更新~

日更较慢有需要完整笔记请私我,C/C++/数据结构-算法/单片机51-STM32-GD32-ESP32/嵌入式/Linux操作系统/uboot/Linux内核-驱动-应用/硬件入门-PCB-layout/Python/后期小程序和机器学习!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小菜狗编程笔记

你的鼓励将是我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值