文章目录提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
- 前言
- 一、什么是文件
- 二、文件的打开和关闭函数
- 1.fopen(文件打开函数)
- 2.fclose(文件关闭函数)
- 三、文件的顺序读写
- 1.fputc
- 2.fgetc
- 3.fputs
- 4.fgets
- 5.fscanf
- 6.fprintf
- 7.fwrite
- 8.fread
- 四、文件的随机读写
- 1.fseek
- 2.ftell
- 3.rewind
- 五、文件读取结束的判定
- 六、文件缓冲区
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
一、什么是文件二、文件的打开和关闭函数 1.fopen(文件打开函数)文件是一组相关数据的有序集合,这个数据集有一个名称,叫做文件名。所有文件都可以通过流进行输入、输出操作。与文本流和二进制流相对应,文件可以分为文本文件和二进制文件。
☆ 文本文件也称为ASCCII文件,保存时每个字符对应一个字节,存放对应的ASCII码。
☆ 二进制文件按二进制编码方式保存文件内容。
按文件内容看,可以分为源文件、目标文件、可执行文件、头文件和数据文件等。
从用户角度看,文件可分为普通文件和设备文件两种。
● 普通文件:指驻留在磁盘或其他外部介质上的有序数据集。
● 设备文件:指与主机相连的各种外部设备,如显示器、打印机、键盘等。
函数原型:
函数说明:filemane为被打开文件的文件名,mode为打开方式。
文件使用方式:
| 文件使用方式 | 含义 |
|---|---|
| “r”(只读) | 为了输入数据,打开一个已经存在的文本文件 出错 |
| “w”(只写) | 为了输出数据,打开一个文本文件 建立一个新的文件 |
| “a”(追加) | 向文本文件尾添加数据 建立一个新的文件 |
| “rb”(只读) | 为了输入数据,打开一个二进制文件 出错 |
| “wb”(只写) | 为了输出数据,打开一个二进制文件 建立一个新的文件 |
| “ab”(追加) | 向一个二进制文件尾添加数据 出错 |
| “r+”(读写) | 为了读和写,打开一个文本文件 出错 |
| “w+”(读写) | 为了读和写,建议一个新的文件 建立一个新的文件 |
| “a+”(读写) | 打开一个文件,在文件尾进行读写 建立一个新的文件 |
| “rb+”(读写) | 为了读和写打开一个二进制文件 出错 |
| “wb+”(读写) | 为了读和写,新建一个新的二进制文件 建立一个新的文件 |
| “ab+”(读写) | 打开一个二进制文件,在文件尾进行读和写 建立一个新的文件 |
2.fclose(文件关闭函数)如果fopen函数在文件打开成功,则返回一个有确定指向的FILE类型指针;若打开失败,则返回NULL。
函数原型:
注意:在文件使用完毕后,不要忘记使用fclose函数将其关闭,防止文件内数据的丢失。
顺序读写函数:
| 功能 | 函数名 | 适用于 |
|---|---|---|
| 字符输入函数 | fgetc | 所有输入流 |
| 字符输出函数 | fputc | 所有输出流 |
| 文本行输入函数 | fgets | 所有输入流 |
| 文本行输出函数 | fputs | 所有输出流 |
| 格式化输入函数 | fscanf | 所有输入流 |
| 格式化输出函数 | fprintf | 所有输出流 |
| 二进制输入 | fread | 文件 |
| 二进制输出 | fwrite | 文件 |
函数应用:
1.fputc函数原型:
代码如下:
//写字符到文件 #include#include int main() { FILE* fp; fp = fopen("test.txt", "w"); if (fp == NULL) { printf("打开文件失败n"); return; } char ch = getchar(); while (ch != '#') { fputc(ch, fp); ch = getchar(); } fclose(fp); fp = NULL; return 0; }
运行结果:
函数原型:
代码如下:
//读字符 #include#include int main() { FILE* fp; fp = fopen("test.txt", "r"); if (fp == NULL) { printf("打开文件失败n"); return; } char ch = fgetc(fp); while (ch != EOF) { printf("%c ", ch); ch = fgetc(fp); } printf("n"); fclose(fp); fp = NULL; return 0; }
运行结果如下
fputs函数:写一个字符串到文件中。
代码:
#include#include int main() { FILE* fp; char ch[20]; fp = fopen("test.txt", "w"); if (fp == NULL) { printf("打开文件失败n"); return; } gets(ch); fputs(ch,fp); printf("n"); fclose(fp); fp = NULL; return 0; }
结果:
fgets函数:从文件读取num个字符到str数组中。
代码:
include#include int main() { FILE* fp; char ch[20]; fp = fopen("test.txt", "r"); if (fp == NULL) { printf("打开文件失败n"); return; } fgets(ch,8,fp); printf("%sn",ch); fclose(fp); fp = NULL; return 0; }
运行结果:
函数原型:
代码:
#include#include struct S { char name[20]; int age; double d; }; int main() { struct S p = { "张三",22,61.5 }; FILE* fp; fp = fopen("test.txt", "w"); if (fp == NULL) { printf("打开文件失败n"); return; } fprintf(fp,"%s %d %.2lfn",p.name,p.age,p.d); fclose(fp); fp = NULL; return 0; }
运行结果:
函数原型:
代码:
#include#include struct S { char name[20]; int age; double d; }; int main() { struct S p = { 0 }; FILE* fp; fp = fopen("test.txt", "r"); if (fp == NULL) { printf("打开文件失败n"); return; } fscanf(fp,"%s %d %.2lfn",p.name,&(p.age),&(p.d)); printf("%s %d %.2lfn", p.name, p.age, p.d); fclose(fp); fp = NULL; return 0; }
运行结果:
fwrite函数:将ptr地址开始的信息输入count次,每次读取size个字节,输入的信息保存到stream指向的文件中。
代码:
#include#include struct S { char name[20]; int age; double d; }; int main() { struct S p[3] = { {"张三",18,56.1}, {"李四",22,3.14}, {"万五",25,36.6}}; FILE* fp; fp = fopen("test.txt", "w"); if (fp == NULL) { printf("打开文件失败n"); return; } //以二进制写入文件中 fwrite(p, sizeof(struct S), 3, fp); fclose(fp); fp = NULL; return 0; }
运行后的文件:
fread函数:从stream指向的文件读取count次,每次读取size个字节,读取的信息保存在ptr地址中。
代码:
#include#include struct S { char name[20]; int age; double d; }; int main() { struct S p[3] = {0}; FILE* fp; fp = fopen("test.txt", "r"); if (fp == NULL) { printf("打开文件失败n"); return; } //读取二进制文件的内容 fread(p, sizeof(struct S), 3, fp); int i = 0; for (i = 0; i < 3; i++) { printf("%s %d %.2lfn", p[i].name, p[i].age, p[i].d); } fclose(fp); fp = NULL; return 0; }
运行结果:
| 起始点 | 表示符号 | 数字表示 |
|---|---|---|
| 文件首 | SEEK–SET | 0 |
| 文件当前位置 | SEEK–CUR | 1 |
| 文件尾 | SEEK–END | 2 |
fseek函数功能:移动文件内部的位置指针。
stream:文件类型指针;
offset:位移量;
origin:起始点;
代码:
#includeint main () { FILE * pFile; pFile = fopen ( "example.txt" , "wb" ); fputs ( "This is an apple." , pFile ); fseek ( pFile , 9 , SEEK_SET ); fputs ( " sam" , pFile ); fclose ( pFile ); return 0; }
运行结果:
ftell函数功能:得到文件中的当前位置,并使用相对于文件头的位移量表示。
代码:
#includeint main() { FILE* pFile; pFile = fopen("example.txt", "wb"); fputs("This is a good day.", pFile); fseek(pFile, 9, SEEK_SET); fputs(" sam", pFile); int n = ftell(pFile); printf("%dn", n); fclose(pFile); return 0; }
运行结果:
rewind函数功能:将位置指针重返文件开头,没有返回值。
代码:
#includeint main() { FILE* fp; fp = fopen("example.txt", "wb"); fputs("This is a good day.", fp); fseek(fp, 9, SEEK_SET); fputs(" sam", fp); int n = ftell(fp); printf("%dn", n); //位置指针重返文件开头 rewind(fp); n = ftell(fp); printf("%dn", n); fclose(fp); return 0; }
运行结果:
牢记:在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束。而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。
1. 文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
例如:
fgetc 判断是否为 EOF .
fgets 判断返回值是否为 NULL .
2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
例如:
fread判断返回值是否小于实际要读的个数。
正确的使用:
文本文件的例子:
#include#include int main(void) { int c; // 注意:int,非char,要求处理EOF FILE* fp = fopen("test.txt", "r"); if(!fp) { perror("File opening failed"); return EXIT_FAILURE; } //fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环 { putchar(c); } //判断是什么原因结束的 if (ferror(fp)) puts("I/O error when reading"); else if (feof(fp)) puts("End of file reached successfully"); fclose(fp); }
二进制文件的例子:
#include六、文件缓冲区enum { SIZE = 5 }; int main(void) { double a[SIZE] = {1.,2.,3.,4.,5.}; FILE *fp = fopen("test.bin", "wb"); // 必须用二进制模式 fwrite(a, sizeof *a, SIZE, fp); // 写 double 的数组 fclose(fp); double b[SIZE]; fp = fopen("test.bin","rb"); size_t ret_code = fread(b, sizeof *b, SIZE, fp); // 读 double 的数组 if(ret_code == SIZE) { puts("Array read successfully, contents: "); for(int n = 0; n < SIZE; ++n) printf("%f ", b[n]); putchar('n'); } else { // error handling if (feof(fp)) printf("Error reading test.bin: unexpected end of filen"); else if (ferror(fp)) { perror("Error reading test.bin"); } } fclose(fp); }
ANSIC 标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。
#include#include int main() { FILE*pf = fopen("test.txt", "w"); fputs("abcdef", pf);//先将代码放在输出缓冲区 printf("睡眠10秒-已经写数据了,打开test.txt文件,发现文件没有内容n"); Sleep(10000); printf("刷新缓冲区n"); fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘) //注:fflush 在高版本的VS上不能使用了 printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了n"); Sleep(10000); fclose(pf); //注:fclose在关闭文件的时候,也会刷新缓冲区 pf = NULL; return 0;
运行上面这个代码后的可以得出一个结论:
因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。
如果不做,可能导致读写文件的问题。



