文章目录
前言
本章是关于C语言文件操作的详解讲解
C语言文件操作
前言
流 (stream) 是与磁盘或其它外围设备关联的数据的源或目的地
使用细节
- 注意 要先判断是不是空指针,不是空指针则是打开(或写入)文件成功
1.为什么使用文件
我们前面学习结构体时,写了通讯录的程序,当通讯录运行起来的时候,可以给通讯录中增加、删除数据,此时数据是存放在内存中,当程序退出的时候,通讯录中的数据自然就不存在了,等下次运行通讯录程序的时候,数据又得重新录入,如果使用这样的通讯录就很难受。
我们在想既然是通讯录就应该把信息记录下来,只有我们自己选择删除数据的时候,数据才不复存在。这就涉及到了数据持久化的问题,我们一般数据持久化的方法有,把数据存放在磁盘文件、存放到数据库等方式。
使用文件我们可以将数据直接存放在电脑的硬盘上,做到了数据的持久化。
2.什么是文件
磁盘上文件是文件
但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)。
2.1程序文件
包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe)
2.2数据文件
文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件
2.3文件名
文件名包含3部分:文件路径+文件名主干+文件后缀
绝对路径:
转义字符,所以是双斜杠
c:\\code\\test.txt
相对路径:
. 表示 当前路径
… 表示 上一级路径
… 表示 上上级路径
图片在源文件同目录下
./图片/background.jpg
图片在源文件上一级文件目录中
../图片/background.jpg
图片在源文件上两级文件目录中
../../图片/background.jpg
3.文件的打开和关闭
3.1前言
文件在读写之前应该先打开文件,在使用结束之后应该关闭文件
文件的类型为 FILE,文件的信息都是保存在结构体变量中,该结构体类型由系统声明,取名FILE
- 注意 只有文件正常打开之后,才需要再进行关闭
3.2打开和关闭
使用时应创建指针来访问
FILE* pf = fopen("test.txt","w");
ANSIC规定使用fopen函数来打开文件,fclose来关闭文件
3.3 fopen参数
第一个参数是文件名(文件路径+文件名主干+文件后缀),第二个参数是文件使用方式
输入=读取 输出=写入
4.文件顺序读写
4.1.字符输入函数
(读取文件内容)
.
.
4.2.字符输出函数
写入(写入到硬盘上进行存储)
.
.
4.3.文本行输入函数
.
- 上图的 4-1 是 4减1 等于3
- 遇见\n会直接返回
.
4.4.文本行输出函数
跟字符输出函数一样,往文件中输出数据,(换行符还是换行的意义)
.
.
4.5.格式化输出函数
.
这里先讲述 格式化输出函数
.
4.6.格式化输入函数
以下代码是先进行了5.格式化输出函数(先创建文件,再写入结构体数据)后从文件中读取数据的
输入:输入到变量,数组等
.
.
4.7.二进制输出
.
.
4.8.二进制输入
以下代码是先进行了 7.二进制输出后(创建文件并编写后)再从文件中读取信息的
.
.
5. 文件的随机读写
注意:下面所说的文件指针并不是改变文件指针的本身,而是光标,也就是要输入或输出的位置
5.1 fseek
根据文件指针的位置和偏移量来定位文件指针
文件中存放的数据都是字符(char类型),每一个偏移量都相对应有一个字符所以在这里不用纠结元素占多少内存,偏移量又是多少
int fseek ( FILE * stream,long int offset,int origin );
- 第一个参数是哪个流
- 第二个参数是移动多少个偏移量(负数是往前移动,正数往后移动)
- 第三个参数有三种选择
- SEEK_CUR 从当前文件指针的位置开始偏移
- SEEK_END 从最后的位置开始偏移
- SEEK_SET 从最前的位置开始偏移
实例:
5.2 ftell
返回文件指针相对于起始位置的偏移量
long int ftell ( FILE * stream );
5.3 rewind
让文件指针的位置回到文件的起始位置
void rewind ( FILE * stream );
文本文件和二级制文件
根据数据的组织形式,数据文件被称为文本文件或者二级制文件
- 数据在内存中都是以二级制的形式存储,如果不加转换的输出到外存,就是二级制文件
- 如果要求在外存上以ASCII码的形式存储,则需要在存储前转换.以ASCII字符的形式存储的文件就是文本文件
一个数据在文件中是怎么存储的?
字符一律以ASCII形存储,数值型数据即可以用ASCII形式存储,也可以使用二级制形式存储.
如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而二级制形式输出,则在磁盘上只占4个字节(VS2013测试)
#include<stdio.h>
int main()
{
int a = 10000;
FILE* pf = fopen("test.txt", "wb");//wb是二级制写入
fwrite(&a, 4, 1, pf);
fclose(pf);
pf = NULL;
return 0;
}
二级制文本打开方式:
7. 文件读取结束的判定
7.1 被错误使用的feof
牢记:在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束.
而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束.
返回值为真时,表示读取文件到达末尾
返回值为假时,则表示没有读取文件到末尾
- 文本文件读取是否结束,判断返回值是否为EOF ( fgetc ),或者NULL ( fgets )
- 二级制文件的读取结束判断,判断返回值是否小于实际要读的个数( fread )
7.2 ferror( )与feof( )的使用
返回值为真时,表示读取文件失败,参数是流
8. 文件缓冲区
ANSIC标准采用"缓冲文件系统"处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块"文件缓冲区"。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。
缓冲区是为了避免频繁使用程序输出\输入,等攒满缓冲区后一次使用程序输出\输出
测试
这里可以得出一个结论
因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件.
如果没有关闭文件 或者 刷新缓冲区 就可能丢失数据
新添内容
sscanf 和 sprintf
这里可以得出一个结论
因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件.
如果没有关闭文件 或者 刷新缓冲区 就可能丢失数据
新添内容
sscanf 和 sprintf
[外链图片转存中…(img-W8jA5fYF-1697425538819)]
[外链图片转存中…(img-GaANFYt8-1697425538819)]
注意 sscanf 和 sprintf与输入输出流无关