目录:
思维导图
一. 文件定义
二. 文件的打开和关闭
三. 文件的顺序读写操作
四. 文件的随机读写操作
五. 文本文件和二进制文件
六. 文件读取结束的判断
七.文件缓冲区
思维导图:
一. 文件定义
1.文件定义
C语言中,文件是指一组相关数据的集合。
不知道大家是否注意到这样的问题:当我们执行一个程序的时候,数据并不会消失,但是当我们程序退出,那么数据就会消失,这是为啥???
当我们运行程序的时候,数据都是加载到内存上的,这样的运行效率会更高。一旦程序退出,内存上的数据就消失了。
当我们把数据存储在磁盘上,我们可以随时随地查看数据,不会存在数据的消失问题。
文件的作用:把数据进行永久化的保存,即使程序退出,数据也是不会消失。
2. 文件分类
2.1 程序文件
包括源程序文件(后缀:.c),目标文件(Windows后缀:.obj),可执行程序(后缀:.exe)
2.2数据文件
数据文件是程序运行时读,写的数据
3.对程序与文件之间关系的理解
二. 文件的打开和关闭
1. 文件指针
在C中:定义一个FILE* (文件指针) 类型的指针,就可以对文件进行各种读和写的操作。
每一个被指定使用的文件都会有一个对应的文件信息区,用来存放当前文件的相关信息(大小,文件位置,文件状态……),这些信息都是通过一个FILE* 类型指针进行维护的。
2文件的基本操作
fopen() 第一个参数:要操作文件的名字
fopen() 函数返回值:
打开文件的方式:
三. 文件的顺序读写操作
1. 相关的函数使用介绍
2. 对文件的使用操作
1)fgetc() fputc()
fgetc() 一旦读取失败或者是遇到文件末尾会返回一个EOF
对于fputc()函数的使用和fgetc()函数使用以及函数操作失败返回值 是一样的。
这两个函数都是对字符进行一个一个操作的
使用栗子:
2)fgets() 和 fputs()
注意:
fgets() 最多只能读取num-1个字符,遇到换行符结束读取,
fgets() fputs()只能是针对性的一行字符串进行处理
每一次打开文件的时候FILE* pf 指针都会默认指向文件内容的起始位置
3)fscanf() fprintf()
fscanf()功能:从流里面读取格式化的数据
fprintf()功能:把格式化的数据写入流里面
使用例子
4)sscanf() sprintf()
sscanf() 函数功能:从字符串里面把数据转成指定的格式化
sprintf() 函数功能: 把指定格式化的数据转换成字符串
使用例子:
5)fread() fwrite()
fread() 函数功能:从流里面读取数据以二进制读的方式(“rb”)
参数介绍:
ptr:把读取之后的数据存放起来
count: 要读取的数据个数
size: 读取每一个数据大小,单位字节
stream:数据流
fread() fwrite()函数参数基本一样;
fwrite() 函数功能:把数据写进一个流里面以二进制写的方式(“wb”)
前者功能是读取一个二进制文件,后者是对一个二进制文件进行写入数据。只不过当我们打开写入之后的这个二进制文件咱是看不懂的。
四. 文件的随机读写操作
不知道大家是否注意到这样一个问题:咱们每一次打开指定的文件的时候,文件指针都会默认指向文件内容的起始位置;如果想要每次打开文件的时候在任意一行的某个位置指定呢???
1. fseek()
fseek() 函数功能:根据文件指针的位置和偏移量重新定义指针的指向位置
函数返回值:成功的话,返回数值0;否则返回非0的数值
参数介绍:
stream:文件指针
offset: 偏移量(非正数即负数)
origin:指定文件指针的位置
2. ftell()
ftell() 函数功能:返回当前指针与起始位置的偏移量。
此函数返回值:也是返回当前指针所在位置距离起始位置的偏移量
3.rewiind()
rewind() 函数功能:让FILE* 类型的指针重新回到文件的起始位置
关于以上3个函数综合应用:
int main()
{int arr[10] = { 0 };FILE* pf = fopen("test.txt", "r");if (pf == NULL){perror("fopen");return 1;}int ch = fgetc(pf);printf("%c\n", ch);//afseek(pf, 5, SEEK_CUR);//注意是从b这个位置偏移5个位置,指向gch = fgetc(pf);printf("%c\n", ch);//gprintf("当前指针距离起始位置的偏移量:%d\n", ftell(pf));//pf每次使用完会自动指向下一个数据的位置,此时指向hrewind(pf);//此时指针从当前位置重新回到文件的起始位置char ret[100] = "xxxxxxx";fgets(ret, 10, pf); //从pf所在位置开始最多读取9个字符放到ret这个数组printf("%s\n",ret);fclose(pf);pf = NULL;return 0;
}
运行结果:
五. 文本文件和二进制文件
根据数据输出的组织形式,数据文件分为文本文件和二进制文件。
数据在内存里面以二进制形式存储,当数据输出的时候不加以任何形式的转换,此时文件称之为二进制文件
但是当数据 输出的时候要求以ASCII码的形式输出到外存(硬盘),此时的文件称之为文本文件。
数据是如何存储在内存里的???
举个例子:数据100000 以字符形式存储和以数值形式存储所占大小是不一样的
数值类型存储占4个字节:
int main()
{int a = 100000;FILE* pf = fopen("test.txt", "wb");if (pf == NULL){perror("fopen()");return -1;}fwrite(&a, sizeof(int), 1, pf);//以数值型存储100000fclose(pf);pf = NULL;return 0;
}
此文件是以二进制编辑方式打开的
关于如何以二进制编辑打方式开指定文件见下:
分析:
100000以ASCII 形式存储占6个字节:
注意:
关于数据大小(单位字节)并不是由数据是以什么形式存储在内存里决定的。
六. 文件读取结束的判断
1. feof()
对于此函数相信有很多老铁会被误导吧!
feof()函数返回值是不能用来判断文件是否读取结束滴!
feof()函数功能:
当用户自己明确知道文件已经读取结束了,调用此函数判读文件是因为读取失败而结束还是遇到文件末尾正常结束的。
1.1
对于文本文件是否读取结束滴返回值的判断应该调用函数fgetc() :对应返回值EOF
fgets()返回值:NULL
1.2
对二进制文件的读取结束判断返回值是否小于实际读取的个数即可
比如:fread() 函数
2. 使用
#include <stdlib.h>int main(){int c; FILE* fp = fopen("test.txt", "r"); //读的方式打开此文件if (fp == NULL) {perror("fopen()");return -1;}while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环{putchar(c);}//判断是读取结束原因//fgetc() 当读取失败的时候或者遇到文件结束的时候,都会返回EOFif (ferror(fp)) // ferror() 判断是否异常结束读取的puts("I/O error when reading");else if (feof(fp))// feof() 明确知道读取结束,判断是否遇到文件末尾结束读取puts("End of file reached successfully");fclose(fp);fp = NULL;return 0;}
七.文件缓冲区
不知道各位是否想过这样一个问题:当我们从文件读取数据的时候,这些数据是瞬间就被成功读取了还是说系统有一定的处理机制呢???
对于这个问题,涉及到文件缓冲区的知识点:
当我们从文件读取数据的时候,这些数据并不是瞬间就被读取了,而是先进入一个内存缓冲区,等到这个缓冲区达到一定条件(比如说:缓冲区满了;又或者是数据读取已经结束了等等),这些数据就会被送到程序数据区;
对于写入数据是一样的道理