长沙网站推广,福建省住建厅网站官网,做暧暧小视频免费网站,广西南宁市网站制作公司一、引言——为什么使用文件 
如果没有文件#xff0c;我们写的程序的数据是存储在电脑的内存中#xff0c;如果程序退出#xff0c;内存回收#xff0c;数据就丢失了#xff0c;等再次运行程序#xff0c;是看不到上次程序的数据的#xff0c;如果要将数据进行持久化的…一、引言——为什么使用文件 
如果没有文件我们写的程序的数据是存储在电脑的内存中如果程序退出内存回收数据就丢失了等再次运行程序是看不到上次程序的数据的如果要将数据进行持久化的保存我们可以使用文件。 
C语言文件操作的意义在于实现数据的持久化以便于数据的读取、存储和处理为程序设计提供方便。程序的数据和各种外部设备之间是怎么联系起来的这里涉及到“流”的概念。 
二、流和标准流 
2.1 流 
我们程序的数据需要输出到各种外部设备也需要从外部设备获取数据不同的外部设备的输入输出操作各不相同为了方便程序员对各种设备进行方便的操作我们抽象出了流的概念我们可以把流想象成流淌着字符的河。 
C程序针对文件、画面、键盘等的数据输入输出操作都是同流操作的。 
一般情况下我们要想向流里写数据或者从流中读取数据都是要打开流然后操作。 
2.2 标准流 
那为什么我们从键盘输入数据向屏幕上输出数据并没有打开流呢? 那是因为C语言程序在启动的时候默认打开了3个流: 
stdin - 标准输入流在大多数的环境中从键盘输入。stdout - 标准输出流大多数的环境中输出至显示器界面。stderr - 标准错误流大多数环境中输出到显示器界面。 
就是因为默认打开了这三个流我们使用scanf、printf等函数就可以直接进行输入输出操作的。stdin、stdout、stderr三个流的类型是:FILE*通常称为文件指针。 C语言中就是通过FILE*的文件指针来维护流的各种操作的。 
三、文件指针 
在C语言中文件指针用于在程序中操作文件。一个文件指针是一个特殊的结构体变量每个被使用的文件都在内存中开辟了一个相应的文件信息区这些信息是保存在一个结构体变量中的。该结构体类型是由系统声明的取名FILE。文件指针用来存放文件的相关信息如文件的名字文件状态及文件当前的位置等。在C语言中所有的输入/输出操作都是通过文件指针完成的。 
每当打开一个文件的时候系统会根据文件的情况自动创建一个FILE结构的变量并填充其中的信息使用者不必关心细节。 
一般都是通过一个FILE的指针来维护这个FILE结构的变量这样使用起来更加方便。 
FILE* pf;//创建一个⽂件指针变量定义pf是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说通过文件指针变量能够间接找到与它关联的文件。 
四、文件的打开和关闭 
文件在读写之前应该先打开文件在使用结束之后应该关闭文件。 
在编写程序的时候在打开文件的同时都会返回一个FILE*的指针变量指向该文件也相当于建立了指针和文件的关系。 
ANSIC规定使用fopen函数来打开文件fclose来关闭文件。 
fopen和fclose函数原型 
//打开文件
FILE * fopen ( const char * filenameconst char * mode );
//关闭文件
int fclose ( FILE * stream );mode表示文件的打开模式下面都是文件的打开模式: 
文件使用方式含义如果指定文件不存在“r”(只读)为了输入数据,打开一个已经存在的文本文件出错“w”(只写)为了输出数据,打开一个文本文件建立一个新的文件“a”(追加)向文本文件尾添加数据建立一个新的文件“rb”(只读)为了输入数据,打开一个二进制文件出错“wb”(只写)为了输出数据,打开一个二进制文件建立一个新的文件“ab”(追加)向一个二进制文件尾添加数据建立一个新的文件“r”(读写)为了读和写,打开一个文本文件出错“w”(读写)为了读和写,建立一个新的文件建立一个新的文件“a”(读写)打开一个文件在文件尾进行读写建立一个新的文件“rb”(读写)为了读和写打开一个二进制文件出错“wb”(读写)为了读和写新建一个新的二进制文件建立一个新的文件“ab”(读写)打开一个二进制文件,在文件尾进行读和写建立一个新的文件 
实例代码举例 
#include stdio.hint main() {FILE *file;// 使用 fopen 函数打开文件file  fopen(test.txt, w);if (file  NULL) {printf(无法打开文件\n);return 1;}// 向文件写入内容fprintf(file, Hello, World!);// 使用 fclose 函数关闭文件fclose(file);return 0;
}在这个例子中我们首先使用 fopen 函数以写入模式 (“w”) 打开一个名为 “test.txt” 的文件。如果文件无法打开例如由于权限问题或文件已存在但不可写fopen 将返回 NULL我们在这种情况下打印一条错误消息并返回 1 以指示程序出错。 
然后我们使用 fprintf 函数向文件写入一条消息。在这里fprintf 的第一个参数是文件指针第二个参数是格式化字符串类似于 printf 函数。 
最后需要使用 fclose 函数关闭文件。这是很重要的因为如果你忘记关闭文件可能会导致数据丢失或其他不可预知的问题。在大多数情况下你应该始终确保在完成对文件的操作后关闭它。 
五、文件的顺序读写 
5.1 顺序读写函数介绍 
函数名功能适用于fgetc字符输入函数将文件中的数据输入到内存中所有输入流fputc字符输出函数所有输出流fgets文本行输入函数所有输入流fputs文本行输出函数所有输出流fscanf格式化输入函数所有输入流fprintf格式化输出函数所有输出流fread二进制输入文件fwrite二进制输出文件 
5.2 函数应用举例 
1.fgetc和fputc函数 
fgetc(一次读取文件中的一个字符到内存中) 
int fgetc ( FILE * stream );//fgetc函数原型#include stdio.hint main(){FILE* file  fopen(data.txt, r);  // 打开名为 data.txt 的文件以供读取if (file  NULL) {printf(无法打开文件\n);return 1;}char ch;while ((ch  fgetc(file)) ! EOF) // 读取文件直到遇到文件结束符EOF{ printf(%c, ch);  // 打印每个读取的字符}fclose(file);  // 关闭文件return 0;
}上面的例子中把data.txt文件中的所有字符内容打印在屏幕上。 data,txt 事先编辑好内容文件内容如下  运行结果如下  
fputc(一次把内存中的一个字符写入到文件中) 
int fputc ( int character, FILE * stream );//fputc函数原型#includestdio.hint main()
{FILE* fp  fopen(data.txt,w);char a[]  hello bit~~;for (int i  0; i  10; i){fputc(a[i], fp);}fclose(fp);return 0;
}代码中使用了 fputc 函数将字符串 “hello bit~~” 的前10个字符写入到 “data.txt” 文件中。  
2.fputs和fgets函数 
fputs函数一次向一个文件写入一行字符串。 
int fputs ( const char * str, FILE * stream );//fputs函数原型#include stdio.hint main() 
{FILE* file  fopen(example.txt, w);  // 打开一个文件以写入if (file  NULL) {printf(无法打开文件\n);return 1;}const char* text  Hello, World!\n;  // 这是我们将要写入的字符串fputs(text, file);  // 将字符串写入到 file 指向的文件fclose(file);  // 关闭文件return 0;
}运行代码后代码路径下生成example.txt文件内容如下  在上述代码中fputs 函数接收两个参数要写入的字符串和一个文件指针。这个函数将字符串写入到文件然后我们使用 fclose 来关闭文件。 
fgets函数一次从一个文件中读取一行字符串。 
char * fgets ( char * str, int num, FILE * stream );//fgets函数原型接下来我们使用 fgets 来从同一个文件中读取这行字符串 
#include stdio.hint main(){FILE *file  fopen(example.txt, r);  // 打开一个文件以读取if (file  NULL) {printf(无法打开文件\n);return 1;}char buffer[100];  // 创建一个缓冲区来保存文件中的字符串fgets(buffer, sizeof(buffer), file);  // 从 file 指向的文件读取字符串到 buffer 中printf(%s, buffer);  // 打印读取到的字符串fclose(file);  // 关闭文件return 0;
}运行结果如下  
在这个代码中fgets 函数接收三个参数一个目标缓冲区缓冲区的大小以及一个文件指针。fgets 将从文件中读取最多大小为缓冲区大小的字符串并保存到缓冲区中。然后我们使用 printf 来打印读取到的字符串最后我们再次使用 fclose 来关闭文件。 
3.fscanf和fprintf函数 
格式化输入输出函数 
int fscanf ( FILE * stream, const char * format, ... );//fscanf函数原型
int fprintf ( FILE * stream, const char * format, ... );//fprintf函数原型
//对比scanf和printf
int scanf ( const char * format, ... );
int printf ( const char * format, ... );通过对以上函数原型的对比可以知道fscanf和fprintf函数这俩个函数使用十分类似fscanf和fprintf是多了一个文件指针参数其他的都和scanf、printf一样。直接看例子 
#include stdio.hint main() {FILE *file;file  fopen(test.txt, w);if (file  NULL) {printf(无法打开文件\n);return 1;}int i;for (i  0; i  10; i) {fprintf(file, 数字 %d\n, i);}fclose(file);return 0;
}在这个例子中我们使用 fopen 打开一个名为 “test.txt” 的文件以写入数据。然后使用 fprintf 将一些数字写入到这个文件中。最后我们使用 fclose 来关闭文件。 
然后我们来看一下 fprintf 的例子 
#include stdio.hint main() {FILE *file;file  fopen(test.txt, r);if (file  NULL) {printf(无法打开文件\n);return 1;}char buffer[100];while (fscanf(file, %s, buffer) ! EOF) {printf(%s\n, buffer);}fclose(file);return 0;
}在这个例子中我们使用 fopen 打开一个名为 “test.txt” 的文件以读取数据。然后使用 fscanf 从这个文件中读取字符串并将其打印出来。当 fscanf 读取到文件结束符EOF时循环终止。最后我们使用 fclose 来关闭文件。 
4. fread和fwrite函数 
fread和fwrite是C语言中的函数它们用于从文件中读取和写入数据。 
fread函数用于从文件中读取数据其语法如下 
size_t fread(void *ptr, size_t size, size_t count, FILE *stream)其中ptr是指向要读取数据的缓冲区的指针size是每个元素的大小count是要读取的元素个数stream是文件流指针。 
fwrite函数用于将数据写入文件中其语法如下 
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream)其中ptr是指向要写入文件的数据的指针size是每个元素的大小count是要写入的元素个数stream是文件流指针。 
这两个函数通常用于二进制文件的读写。  在读写时必须使用二进制模式需要注意文件的打开方式如只读wb、只写rb、追加ab等以及文件指针的位置。 这里有一个小知识点fread和fwrite是有返回值的fread和fwrite的返回值是size_t类型的整数值表示函数成功读取或写入的元素个数。 正常读取或写入操作情况下返回值都应该是函数参数中包含的元素个数即等于size_t count 如果读取或写入操作失败fread和fwrite将返回一个比预期小的值。例如如果你试图读取10个元素但只读取了5个那么fread将返回5。同样如果你试图写入10个元素但只写入了5个那么fwrite将返回5。 你可以使用fread和fwrite的返回值来检查是否成功读取或写入了预期数量的元素。如果返回值与预期不符则可能需要处理错误或采取其他措施。 举例 假设你有一个名为“input.txt”的文本文件其内容如下所示 
This is an example.
It shows how to use fread and fwrite.下面是一个C程序它读取“input.txt”文件中的内容将其写入一个新文件“output.txt”中并输出成功读取和写入的元素个数 
#include stdio.hint main() {FILE *input_file, *output_file;char buffer[1024];size_t bytes_read, bytes_written;// 打开输入文件input_file  fopen(input.txt, rb);if (input_file  NULL) {fprintf(stderr, 无法打开输入文件\n);return 1;}// 打开输出文件output_file  fopen(output.txt, wb);if (output_file  NULL) {fprintf(stderr, 无法打开输出文件\n);fclose(input_file);return 1;}// 使用fread和fwrite进行读写操作while ((bytes_read  fread(buffer, sizeof(char), sizeof(buffer), input_file)) ! 0) {bytes_written  fwrite(buffer, sizeof(char), bytes_read, output_file);printf(已读取 %zu 个元素已写入 %zu 个元素\n, bytes_read, bytes_written);}// 关闭文件fclose(input_file);fclose(output_file);printf(读取和写入完成\n);return 0;
}运行该程序后它将输出以下内容 
已读取 27 个元素已写入 27 个元素
已读取 27 个元素已写入 27 个元素
读取和写入完成六、文件的随机读写 
在C语言中可以使用以下函数来实现文件的随机读写 
函数名用途fseek()用于设置文件指针的位置。可以使用的文件指针位置模式包括SEEK_SET从文件开头算起、SEEK_CUR从当前位置算起和SEEK_END从文件末尾算起。ftell()用于获取当前文件指针的位置。rewind()让文件指针的位置回到文件的起始位置fread()用于从文件中读取数据。可以指定读取的元素大小和数量以及文件指针的位置。fwrite()用于将数据写入文件中。可以指定要写入的数据大小和数量以及文件指针的位置。 6.1 fseek 
int fseek ( FILE * stream, long int offset, int origin );int fseek(FILE *stream, long int offset, int origin )
参数:
stream -- 这是指向 FILE 对象的指针该 FILE 对象标识了流。
offset -- 这是相对 whence 的偏移量以字节为单位。
origin -- 参照点可以是 SEEK_SET从文件开始位置开始移动SEEK_CUR从当前位置开始移动或 SEEK_END从文件末尾开始移动。返回值:
如果成功则该函数返回零否则返回非零值。6.2 ftell 
long int ftell ( FILE * stream );long int ftell(FILE *stream)
参数
stream -- 这是指向 FILE 对象的指针该 FILE 对象标识了流。返回值
ftell 函数的返回值是当前文件指针的位置偏移量以字节为单位从文件的开头开始计算。6.3 rewind 
void rewind(FILE *stream);//函数原型//代码举例↓↓↓↓
/* rewind example */
#include stdio.h
int main ()
{int n;FILE * pFile;char buffer [27];pFile  fopen (myfile.txt,w);for ( nA ; nZ ; n)fputc ( n, pFile);rewind (pFile);fread (buffer,1,26,pFile);fclose (pFile);buffer[26]\0;printf(buffer);//等价于printf(%s,buffer);return 0;
}以上代码的运行结果如下  以上代码的意思是 
首先使用一个循环用fputc把大写字母’A’到大写字母‘Z’这26个字符写入到名为’myfile.txt’的文件中写完之后这时文件指针指向的位置是文件的末尾使用rewind()函数让文件指针的位置回到文件的起始位置接着再使用fread()函数从头到尾把文件的内容读取到buffer数组中然后给数组buffer最后一个元素设置为\0加上字符串的结束标志最后使用printf函数以字符串的形式打印buffer数组中的内容。 6.4 代码举例 
使用这些函数可以实现文件的随机读写例如 
FILE *fp;
char buffer[100];
int num;fp  fopen(file.txt, r);  // 打开文件
if(fp  NULL) {printf(Error opening file\n);return -1;
}fseek(fp, 10, SEEK_SET);  // 将文件指针移动到第10个字节处
num  fread(buffer, sizeof(char), 20, fp);  // 从当前位置读取20个字节存储到buffer数组中
fclose(fp);  // 关闭文件上述代码中首先使用fopen()函数打开文件然后将文件指针移动到第10个字节处从当前位置读取20个字节并将其存储到buffer数组中最后使用fclose()函数关闭文件。 
七、文件读取结束的判定 
C语言文件操作过程中避免不了对文件结束的判定特别是读取文件数据到内存中去的时候不可能让程序一直读取文件中的内容不停止而是当文件中所有内容都读到内存中后结束文件读取的操作。 
7.1 feof 
关于文件结束的判定首先要了解一个函数feof 
int feof ( FILE * stream );//函数原型该函数的返回值有两种可能 如果文件读取操作结束不是 因为文件已经到达末尾feof() 函数返回 0即 false。 如果文件读取操作结束是因为文件已经到达末尾feof() 函数返回非零值即 true。 需要注意的是在文件读取过程中不能用feof函数的返回值直接来判断文件的是否结束。 
feof 的作用是当文件读取结束的时候判断是读取结束的原因是否是遇到文件尾结束。 
以下是使用feof()函数的基本例子 
#include stdio.hint main() 
{FILE *file  fopen(test.txt, r);if (file  NULL) {printf(Failed to open file\n);return 1;}char ch;while (!feof(file)) {ch  fgetc(file);if (ch ! EOF) {printf(%c, ch);}}fclose(file);return 0;
}在这个例子中我们使用fgetc()函数一次读取一个字符然后使用feof()检查是否到达文件末尾。如果feof(file)返回非零值就意味着文件正常读取结束文件指针已经到达文件末尾所以循环停止。 
需要注意的是即使在最后一次读取之后feof()仍然会返回非零值因为它只是在读取操作之前检查文件状态。换句话说如果你在最后一次读取操作之后再次调用feof()它仍然会返回非零值。如果你想在最后一次读取操作之后确认文件已经读取结束你需要使用ferror()函数来检查是否有其他错误发生。 
7.2 fgets()或者getc() 
另一种判定文件是否已经读取到结束的方法是使用fgets()或getc()等读取函数读取文件然后检查结果是否为EOF。例如 
#include stdio.hint main() 
{FILE *file  fopen(test.txt, r);if (file  NULL){printf(Failed to open file\n);return 1;}char buffer[100];while (fgets(buffer, 100, file) ! NULL){printf(%s, buffer);}fclose(file);return 0;
}在这个例子中我们使用fgets()函数一次读取一行当fgets()返回NULL时意味着已经到达文件末尾。