Bootstrap

C语言-文件操作


在这里插入图片描述

🎯引言

在计算机编程领域,文件操作是一项基础且关键的技能。无论是读取配置文件、保存用户数据,还是处理日志信息,文件操作都扮演着重要角色。特别是在C语言中,文件操作的学习不仅帮助我们理解计算机如何管理数据存储,还能够深入理解内存与磁盘之间的交互机制。本文将深入探讨C语言中文件操作的各个方面,包括如何打开和关闭文件、读取和写入文件内容,以及如何管理文件指针和处理文件缓冲区等内容。

👓文件操作

1.为什么使用文件

数据持久化:文件可以用来保存数据,以便在程序结束后仍能访问这些数据。这样,即使计算机关机或程序崩溃,数据也不会丢失。

下面通过一段简单示例来讲解:

#include <stdio.h>

int main()
{
    int a=0;
    scanf("%d",&a);
    printf("%d",a);
    
    return 0;
}

我们平时所写的程序的数据都是存储在电脑内存中,如果我们将程序退出,内存就会自动回收数据也就丢了,再次运行程序就没有上次程序的数据.就像上面的代码,我第一次运行他,输入a的值,下一次运行a的值就不存在了.所以我们要通过文件的方式将数据保存下来.

数据共享:文件可以在不同的程序或设备之间传输和共享数据。例如,一个程序可以将数据写入文件,另一个程序可以读取这些文件来获取数据。

存储大数据:文件可以存储大量数据,而这些数据可能不适合全部加载到内存中。通过文件,程序可以处理超出内存容量的大量数据。

备份和恢复:文件可以用来备份重要数据,防止数据丢失。例如,数据库可以将数据定期导出到文件中,以便在数据损坏或丢失时进行恢复。

2.什么是文件

文件是存储在计算机存储介质(如硬盘、固态硬盘、光盘等)上的一组数据,它具有特定的格式和结构,用于保存信息。

通常我们所接触到的有两种文件:程序文件,数据文件(从文件功能的角度分类).

2.1程序文件

程序文件是一种包含可执行代码或指令的文件,用于计算机执行特定任务或程序。根据文件的用途和编程语言的不同,程序文件可以分为多种类型。如:源程序文件(.c),目标文件(Windows下后缀为.obj),以及可执行程序(Windows下后缀为.exe).

2.2数据文件

数据文件是用于存储数据而非可执行代码的文件。它们在程序执行过程中或之后被读取和写入,用于保存各种类型的信息。(下面我所讲的内容都是与数据文件有关的)

之前我们利用的scanf从键盘上接收数据到内存中,是通过标准输入流(后面会讲解相关概念)进行的,将数据打印到屏幕是通过标准输出流进行的.

图示:

在这里插入图片描述

我们信息的输出和输入,不止通过键盘和鼠标,还可以通过磁盘进行,会从磁盘上读取信息,也会把信息输出到磁盘上,下面会详细讲解.

2.3文件名

我们要找到一个文件,就必须找到该文件的唯一标识,这个标识就文件名.

文件名包括:文件路径+文件名主干+文件名后缀

文件路径:文件路径是文件在文件系统中的位置。它可以是相对路径(相对于当前工作目录)或绝对路径(从根目录开始的完整路径)。

如:C:\Users\JohnDoe\Documents\example.txt那么C:\Users\JohnDoe\Documents\就是文件的路径,example是文件名主干,文件后缀是.txt,所以C:\Users\JohnDoe\Documents\example.txt就是一个文件名.

3.二进制文件和文本文件

二进制文件和文本文件是两种基本的文件类型,用于存储不同类型的数据。理解它们的区别和用途对于数据处理和编程非常重要。

3.1文本文件

文本文件以可读的文本形式存储数据,通常使用字符编码(如ASCII或UTF-8)来表示字符。这些文件可以用任何文本编辑器打开和编辑。

特征

  1. 可读性:文本文件包含人类可读的字符,可以直接查看和编辑。
  2. 编码方式:使用字符编码(如ASCII、UTF-8、UTF-16)来表示字符。
  3. 扩展名:常见的扩展名包括 .txt.csv.html.xml.json 等。
  4. 用途:用于存储纯文本数据、配置文件、源代码、日志文件等。

3.2二进制文件

二进制文件以二进制格式存储数据,即0和1的序列。这些文件通常包含特定格式的数据,无法直接用文本编辑器查看和编辑,必须使用相应的软件进行处理。

特征

  1. 不可读性:二进制文件包含计算机理解的二进制数据,通常对人类不可读。
  2. 数据存储:以二进制格式存储数据,紧凑且高效。
  3. 扩展名:常见的扩展名包括 .bin.exe.jpg.mp3.dat 等。
  4. 用途:用于存储程序执行文件、图像、音频、视频、压缩文件、数据库文件等。

图示讲解:

在外存中以二进制的形式存储就是二进制文件.在外存中以ASCII码的形式存储的文件就是文本文件

如果内存有整数10000(十进制),分别以两种形式存储到外存中会有什么区别呢?下面我将通过图示带你了解他们的区别

二进制文件:

在这里插入图片描述

文本文件:

在这里插入图片描述

以文本文件存储在硬盘中在磁盘上占用五个字节,以二进制文件存储,在磁盘上占四个字节.

4.文件的打开和关闭

4.1流和标准流

在C语言中,**流(stream)**是一个用于处理输入输出的抽象概念。流表示数据的有序序列,数据可以从流中读出或写入流中。每个打开的文件对应一个流,标准库函数通过流来处理文件操作。

流我们可以想象成河流,河流中有许多的鱼,这些鱼我们就可以把他比作是数据,人会从河流中抓鱼,和养鱼,这个过程我们就可以看作程序中的相关操作.

一般情况下,我们想要向流里写数据,或者从流中读取数据,都是要打开流,然后进行操作.类似的,我们要进行抓鱼养鱼,也要走去河流旁边.

标准流:

为什么我们从键盘输入数据,向屏幕上输出数据,没有打开流呢?因为C语言程序启动时,就默认打开了三个流,如下.

C语言提供了三种标准流(程序启动时默认打开):

  • 标准输入(stdin):通常连接到键盘,用于从标准输入设备读取数据。scanf函数就是从该流中读取数据
  • 标准输出(stdout):通常连接到显示器,用于向标准输出设备写入数据。printf函数就是将信息输出到该流中
  • 标准错误(stderr):通常连接到显示器,用于向标准错误设备写入错误信息。

stdin,stdout,stderr有共同的类型是:FILE* ,该类型称为文件指针

C语言中就是通过,FILE*来维护流的各种操作

4.2文件指针

当文件中信息想在程序当中使用时,这个被使用的文件都会在内存开辟一个文件信息区,用来存放文件的相关信息.这些信息是保存在一个结构体变量中的.该结构体类型是由系统声明的,取名为FILE.

在标准C库中,FILE 结构体的定义通常是不公开的typedef struct _IO_FILE FILE;我们不要去关心该结构体的具体内容,我们只要知道,我们通过FILE* 来维护和操作FILE结构的变量,实际上也就是在操作文件了.

4.3文件的打开和关闭

在C语言中,文件的打开和关闭是进行文件操作的基本步骤,使用标准库函数来完成。以下是关于文件的打开和关闭的详细说明和示例:

4.3.1打开文件

在C语言中,可以使用 fopen 函数来打开文件。fopen 函数的原型如下:

FILE *fopen(const char *filename, const char *mode);
  • filename 参数是要打开的文件的路径和名称。
  • mode 参数是一个字符串,用于指定文件的打开模式。常见的模式包括:
    1. 读取模式 ("r")
      • 含义:打开文件进行读取。
      • 操作:如果文件不存在,fopen 函数返回 NULL。文件指针定位在文件的开头。
    2. 写入模式 ("w")
      • 含义:打开文件进行写入,如果文件存在则截断文件(即清空文件),如果文件不存在则创建文件。
      • 操作:如果文件不存在,会创建一个新文件。如果文件已存在,打开时会清空文件的内容。
    3. 追加模式 ("a")
      • 含义:打开文件进行写入,如果文件存在则在文件末尾追加数据,如果文件不存在则创建文件。
      • 操作:如果文件不存在,会创建一个新文件。文件指针定位在文件的末尾,写入数据时会从文件末尾开始追加。
    4. 二进制模式 ("b")
      • 含义:以二进制模式打开文件,通常与上述模式结合使用,如 "rb", "wb", "ab"
      • 操作:在某些系统中,特别是在Windows中,二进制模式可以确保文件内容以二进制方式读取或写入,而不会进行换行符的转换。
    5. 更新模式 ("+")(可与上述模式结合使用,如 "r+", "w+", "a+", "rb+", "wb+", "ab+"
      • 含义:允许文件进行读写操作,即可以读取和写入文件。
      • 操作:文件指针可以在文件中移动,读取和写入操作可以在文件中任意位置进行(除了a+与ab+他们都是在文件末尾进行写入数据的)。

文件不存在时的情况

  • 如果在打开文件时指定的模式不包括 wa,而且文件不存在,fopen 函数将返回 NULL,表示文件打开失败。例如,如果指定 "r" 模式打开一个不存在的文件,fopen 将返回 NULL,因为这种模式要求文件必须存在才能进行读取操作。
  • "w""a" 模式下,如果文件不存在,fopen 函数会尝试创建一个新文件。如果文件创建成功,它将打开并准备进行写入操作。如果在打开时出现错误(如权限不足),则可能返回 NULL

下面我们通过w模式进行演示:

#include <stdio.h>

int main()
{
	//写入
	FILE* pflie = fopen("test.txt", "w");

	//打开文件失败,直接退出程序
	if (pflie == NULL)
	{
		return 1;
	}

	//向文件写入信息
	fputs("abcdef", pflie);

	fclose(pflie);
	pflie = NULL;

	return 0;
}

代码解析:

  1. 如果没有test.txt文件的话,会在当前路径地下创建一个新的文件test.txt
  2. 如果原先有文件,文件的内容会被清空,然后通过fputs向文件输入信息.
4.3.2关闭文件

使用 fclose 函数关闭打开的文件。fclose 函数的原型如下:

int fclose(FILE *stream);
  • stream 参数是一个指向 FILE 结构的指针,表示要关闭的文件

为什么要关闭文件?

关闭文件是一个重要的操作,有几个关键的原因:

  1. 释放资源
    • 操作系统为每个打开的文件分配了资源,包括内存缓冲区和文件描述符等。如果不关闭文件,这些资源将一直占用,可能导致系统资源耗尽,特别是在处理大量文件或长时间运行的程序中。
  2. 确保数据完整性
    • 在写入文件时,数据通常首先存储在内存缓冲区中,并随后被写入到磁盘。如果不关闭文件,数据可能会停留在缓冲区中,而不会被完全写入磁盘。这可能导致数据丢失或文件内容不完整。
  3. 避免文件损坏
    • 如果文件在程序运行时意外关闭(如程序崩溃),操作系统通常会确保文件被正确地关闭和保存。如果文件没有被关闭,那么文件可能会处于打开状态,导致文件损坏或内容丢失。
  4. 遵循最佳实践
    • 关闭文件是良好的编程习惯和文件管理的一部分。这有助于保持代码的清晰性和可维护性,并降低出现文件操作错误的可能性。

5.文件的顺序读写

5.1 读取文件

详细说明

  1. fgetc 函数
int fgetc(FILE *stream);

fgetc 函数(适用所有流):

  • 作用: 从文件中读取一个字符。
  • 返回值: 返回读取的字符(强制转换为 int 类型)。如果到达文件末尾或发生错误,返回 EOF
  • 使用场景: 适用于逐个字符读取的情况,例如读取文本文件中的所有字符。

示例:

#include <stdio.h>

int main() {
    FILE *file = fopen("test.txt", "r");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    int ch;
    while ((ch = fgetc(file)) != EOF) {
        putchar(ch); // 打印读取的字符
    }

    fclose(file);
    return 0;
}
  1. fgets 函数
char *fgets(char *str, int n, FILE *stream);

fgets 函数(使用所有流):

  • 作用: 从文件中读取一行,最多读取 n-1 个字符,并将这些字符存储到 str 中。读取的行以 '\0' 结尾。
  • 返回值: 如果成功,返回 str。如果到达文件末尾或发生错误,返回 NULL
  • 使用场景: 适用于逐行读取的情况,例如读取配置文件或日志文件的每一行。

示例:

#include <stdio.h>

int main() {
    FILE *file = fopen("test.txt", "r");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    char buffer[100];
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("%s", buffer); // 打印读取的行
    }

    fclose(file);
    return 0;
}
  1. fread函数
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

fread 函数从文件中读取二进制数据,将其存储到 ptr 指向的缓冲区中。size 是每个元素的大小(以字节为单位),nmemb 是要读取的元素数量。函数返回读取的元素数量。

fread 函数(使用文件输入流):

  • 作用: 从文件中读取二进制数据,将其存储到 ptr 指向的缓冲区中。
  • 返回值: 返回成功读取的元素数量。
  • 使用场景: 适用于读取二进制文件中的数据,例如图像文件或音频文件。

示例:

#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE *file = fopen("test.bin", "rb");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    // 假设我们知道文件中有 10 个 int 类型的数据
    int data[10];
    size_t read_count = fread(data, sizeof(int), 10, file);
    if (read_count != 10) {
        perror("读取数据时发生错误");
    } else {
        for (size_t i = 0; i < read_count; ++i) {
            printf("%d ", data[i]);
        }
        printf("\n");
    }

    fclose(file);
    return 0;
}

5.2写入文件

1.fputc 函数

int fputc(int char, FILE *stream);

fputc 函数将一个字符写入到指定的文件中。char 是要写入的字符,stream 是文件指针。

返回值

  • 成功时返回写入的字符(强制转换为 unsigned char 类型)。
  • 失败时返回 EOF,并设置 errno 以指示错误。

示例

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "w");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

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

    fclose(file);
    return 0;
}

2.fputs 函数

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

fputs 函数将一个字符串写入到指定的文件中。str 是要写入的字符串,stream 是文件指针。

返回值

  • 成功时返回非负值。
  • 失败时返回 EOF,并设置 errno 以指示错误。

示例

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "w");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    fputs("Hello, World!\n", file);
    fputs("Welcome to C programming.\n", file);

    fclose(file);
    return 0;
}

3.fwrite 函数

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

fwrite 函数将二进制数据写入到指定的文件中。ptr 是源数据缓冲区,size 是每个元素的大小(以字节为单位),nmemb 是要写入的元素数量,stream 是文件指针。

返回值

  • 成功时返回写入的元素数量。
  • 失败时返回一个小于 nmemb 的值,并设置 errno 以指示错误。

示例

#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE *file = fopen("example.bin", "wb");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    int data[] = {1, 2, 3, 4, 5};
    size_t elements_written = fwrite(data, sizeof(int), 5, file);
    if (elements_written != 5) {
        perror("写入数据时发生错误");
    }

    fclose(file);
    return 0;
}

5.3fprintf printf sprintf fscanf scanf sscanf的使用

5.3.1fprintfprintfsprintf 函数

这些函数用于格式化输出。

1.fprintf

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

fprintf 将格式化的数据写入到指定的文件流中。

  • 参数:
    • FILE *stream: 文件指针,指定输出的文件。
    • const char *format: 格式控制字符串。
    • ...: 可变参数,指定要输出的值。
  • 返回值: 成功时返回写入的字符数,失败时返回负值。

示例

#include <stdio.h>

int main() {
    FILE *file = fopen("output.txt", "w");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    fprintf(file, "Name: %s, Age: %d\n", "Alice", 30);
    fclose(file);
    return 0;
}

2.printf

int printf(const char *format, ...);

printf 将格式化的数据输出到标准输出(通常是控制台)。

  • 参数:
    • const char *format: 格式控制字符串。
    • ...: 可变参数,指定要输出的值。
  • 返回值: 成功时返回写入的字符数,失败时返回负值。

示例

#include <stdio.h>

int main() {
    printf("Name: %s, Age: %d\n", "Alice", 30);
    return 0;
}

sprintf

int sprintf(char *str, const char *format, ...);

sprintf 将格式化的数据写入到字符串中。

  • 参数:
    • char *str: 指向存储结果的字符串的指针。
    • const char *format: 格式控制字符串。
    • ...: 可变参数,指定要输出的值。
  • 返回值: 成功时返回写入的字符数,失败时返回负值。

示例

#include <stdio.h>

int main() {
    char buffer[100];
    sprintf(buffer, "Name: %s, Age: %d\n", "Alice", 30);
    printf("%s", buffer);
    return 0;
}
5.3.2fscanfscanfsscanf 函数

这些函数用于格式化输入。

1.fscanf

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

fscanf 从指定的文件流中读取格式化的数据。

  • 参数:
    • FILE *stream: 文件指针,指定输入的文件。
    • const char *format: 格式控制字符串。
    • ...: 可变参数,指向存储读取值的变量。
  • 返回值: 成功读取并赋值的项目数,遇到错误或文件结束时返回 EOF

示例

#include <stdio.h>

int main() {
    FILE *file = fopen("input.txt", "r");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }
	
    //文件中,要有对应的类型才能正确读取
    char name[50];
    int age;
    fscanf(file, "%s %d", name, &age);
    printf("Name: %s, Age: %d\n", name, age);
    fclose(file);
    return 0;
}

2.scanf

int scanf(const char *format, ...);

scanf 从标准输入(通常是键盘)读取格式化的数据。

  • 参数:
    • const char *format: 格式控制字符串。
    • ...: 可变参数,指向存储读取值的变量。
  • 返回值: 成功读取并赋值的项目数,遇到错误或文件结束时返回 EOF

示例

#include <stdio.h>

int main() {
    char name[50];
    int age;
    scanf("%s %d", name, &age);
    printf("Name: %s, Age: %d\n", name, age);
    return 0;
}

sscanf

int sscanf(const char *str, const char *format, ...);

sscanf 从字符串中读取格式化的数据。

  • 参数 :

    • const char *str: 输入字符串。
    • const char *format: 格式控制字符串。
    • ...: 可变参数,指向存储读取值的变量。
  • 返回值: 成功读取并赋值的项目数,遇到错误时返回 EOF

示例

#include <stdio.h>

int main() {
    char input[] = "Alice 30";
    char name[50];
    int age;
    sscanf(input, "%s %d", name, &age);
    printf("Name: %s, Age: %d\n", name, age);
    return 0;
}

6.文件的随机读写

6.1 fseek 函数

int fseek(FILE *stream, long int offset, int origin);

fseek 函数用于将文件指针移动到文件中的指定位置。

参数

  • FILE *stream: 文件指针,指定要操作的文件。

  • long int offset: 偏移量,以字节为单位,正值表示向文件末尾方向移动,负值表示向文件开头方向移动。

  •   int origin
    

    : 指定移动的起始位置,可以是以下三个常量之一:

    • SEEK_SET: 文件开头
    • SEEK_CUR: 当前位置
    • SEEK_END: 文件末尾

返回值

  • 成功时返回 0
  • 失败时返回非零值,并设置 errno 以指示错误。

示例

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "rb");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    // 将文件指针移动到文件开头之后的 10 个字节处
    fseek(file, 10, SEEK_SET);

    // 读取当前位置的字符
    int ch = fgetc(file);
    if (ch != EOF) {
        printf("Character at position 10: %c\n", ch);
    }

    fclose(file);
    return 0;
}

6.2ftell 函数

long int ftell(FILE *stream);

ftell 函数用于获取文件指针当前的位置(相对于文件开头的字节偏移量)。

参数

  • FILE *stream: 文件指针,指定要操作的文件。

返回值

  • 成功时返回文件指针的当前位置(以字节为单位的偏移量)。
  • 失败时返回 -1L,并设置 errno 以指示错误。

示例

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "rb");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    // 将文件指针移动到文件开头之后的 10 个字节处
    fseek(file, 10, SEEK_SET);

    // 获取文件指针的当前位置
    long int position = ftell(file);
    if (position != -1L) {
        printf("Current position: %ld\n", position);
    }

    fclose(file);
    return 0;
}

6.2 rewind 函数

void rewind(FILE *stream);

rewind 函数将文件指针重新定位到文件的开头,并清除文件指针的错误和 EOF 状态。

参数

  • FILE *stream: 文件指针,指定要操作的文件。

示例

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "rb");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    // 将文件指针移动到文件开头之后的 10 个字节处
    fseek(file, 10, SEEK_SET);

    // 使用 rewind 函数将文件指针重新定位到文件开头
    rewind(file);

    // 获取文件指针的当前位置
    long int position = ftell(file);
    if (position != -1L) {
        printf("Current position after rewind: %ld\n", position);
    }

    fclose(file);
    return 0;
}

7.文件读取结束的判定

7.1feof函数的使用

feof 函数

int feof(FILE *stream);

feof 函数用于检查文件指针是否已经到达文件末尾(EOF)。

参数

  • FILE *stream: 文件指针,指定要检查的文件。

返回值

  • 如果文件指针到达文件末尾,则返回非零值(通常是 1)。
  • 如果文件指针未到达文件末尾,则返回零。

使用场景

feof 函数通常在读取文件的循环中使用,以便检测何时到达文件末尾,从而终止读取操作。

示例

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "r");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

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

    if (feof(file)) {
        printf("\n已到达文件末尾。\n");
    } else {
        printf("\n读取文件时发生错误。\n");
    }

    fclose(file);
    return 0;
}

详细说明

  • 作用: feof 函数检查文件指针是否到达文件末尾。这在文件读取过程中非常有用,可以防止读取超出文件内容。
  • 使用方法:
    • 打开文件。
    • 读取文件内容,在读取操作中检查是否到达文件末尾。
    • 根据 feof 的返回值确定是否已到达文件末尾。

注意事项

  • feof 仅在尝试读取文件并且读取操作返回 EOF 后,才会返回非零值。因此,必须在读取操作失败(返回 EOF)之后调用 feof,才能正确判断是否到达文件末尾。
  • 如果读取操作由于其他原因失败(例如文件错误),feof 也可能返回零。在这种情况下,应检查其他文件错误状态,例如通过 ferror 函数

feofferror 结合使用

为了更准确地处理文件读取错误,通常将 feofferror 结合使用,以区分文件末尾和读取错误。

示例

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "r");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

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

    if (feof(file)) {
        printf("\n已到达文件末尾。\n");
    } else if (ferror(file)) {
        printf("\n读取文件时发生错误。\n");
    }

    fclose(file);
    return 0;
}

8.文件缓冲区

文件缓冲区是一块内存,用于临时存储从文件读取的数据或准备写入到文件的数据。数据在缓冲区填满后才会实际写入文件。读取操作也是在缓冲区为空时才会实际从文件中读取数据。缓冲区提高了文件读写操作的效率,因为它减少了直接与磁盘交互的次数。

图示:

在这里插入图片描述

使用fflush刷新缓冲区:

#include <Windows.h>
#include <stdio.h>
int main() {
    FILE* file = fopen("example1.txt", "w");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }


    fputs("刷新缓冲区", file);
    //睡眠10秒,我们这时候看文件中,是没有内容的
    Sleep(10000);
    
    //没刷新缓冲区前.数据不会写到文件中
    fflush(file);
    Sleep(1000);

    //fclose关闭文件的时候,也会刷新缓冲区
    fclose(file);
    return 0;
}

🥇结语

通过本文的学习,我们详细了解了C语言中文件操作的基础知识和实际应用。文件操作不仅限于简单的读写,它还涉及到如何有效地管理内存和磁盘资源,以及如何处理各种异常情况和错误。掌握好文件操作的技能,不仅可以提升我们的编程效率,还能够让我们更加深入地理解计算机系统的底层工作原理。希望本文能够帮助读者建立起坚实的文件操作基础,并在实际项目中得到应用和延展。

;