【C 语言】深度剖析文件操作 [进阶篇 _ 复习专用]
前情提要
本章节就进入 C 语言的核心:深度剖析 C 语言文件操作
接下来我们即将进入一个全新的空间,对代码有一个全新的视角~
以下的内容一定会让你对 C 语言有一个颠覆性的认识哦!!!
以下内容干货满满,跟上步伐吧~
💡本章重点
文件
文本文件操作函数
文本文件和二进制文件
文件缓存区
🍞一.文件
🥐Ⅰ.为什么使用文件
在我们已知 C 语言程序是无法保存数据的,在程序退出时数据便自然不在了,这是因为程序运行时存储的数据都在临时空间上,一旦程序结束,空间便被释放销毁,所以数据无法保存
❓如果我们想将数据持久化,我们该怎么办呢
➡️以下,便引出我们的文件操作
啦~
使用文件可以将数据直接放到电脑硬盘上,做到数据的持久化
🥐Ⅱ.什么是文件
💡一般我们称:
磁盘上的文件是文件
👉通过上述我们可了解到:
文件分为两种(从文件功能的角度来分类):
1️⃣程序文件
① 源程序文件(后缀为.c)
②目标文件(windows 环境后缀为.obj)
③可执行程序(windows 环境后缀为.exe)
2️⃣数据文件
①文件的内容不一定是程序,而是程序运行时读写的数据
②比如:程序运行需要从中读取数据的文件,或者输出内容的文件
🥐Ⅲ.文件名
💡一个文件要有一个唯一的文件标识,以便用户识别和引用
➡️文件名包含三部分:
文件路径+文件名主干+文件后缀
👉Eg: c:
\ code
\ test.txt
🥯Ⅳ.总结
✨综上: 就是对文件
的概述了~
但我们如何在程序中实际操作文件呢?
以下便引出了我们的文件文本操作函数
🍞二.文本文件操作函数
🥐Ⅰ.文件指针
💡在 C 语言中,每当我们想对文件进行操作时:
1️⃣文件先在内存中开辟了一个相应的
文件信息区
,用来存放文件的相关信息【如文件的名字,文件状态及文件当前的位置等】2️⃣而文件信息区在 C 语言中实则是保存在一个系统声明为
FILE
的结构体变量
中
❗特别注意:
每当打开一个文件的时候,系统会根据文件的情况
自动
创建一个FILE
结构的变量,并填充其中的信息,使用者不必关心细节
➡️而期间 C 语言为了更加方便的对FILE
这个存储文件信息的结构体变量进行操作,我们便可以使用文件指针变量
:
⬆️定义pf
是一个指向FILE
类型数据的指针变量
这样我们就可以使
pf
指向某个文件的文件信息区
(是一个结构体变量),即指向FILE
的结构体变量一般定义
FILE*
的指针是为了更方便于我们利用文件指针
去维护/访问
这个结构体变量【文件信息区】
✨综上:
我们对文件进行操作,实际上是利用
文件指针
这个结构体变量对文件信息区
【FILE
这个结构体变量】进行操作也就是说:通过文件指针变量能够找到与它关联的文件
🥐Ⅱ.文件的打开和关闭
🧇1.fopen 函数
💡fopen
函数的作用: 操控程序打开磁盘中的文件
函数的参数:
filename
为想要打开文件的文件名
mode
为文件的打开方式
函数的返回值: 返回的是指向此文件的文件信息区的起始地址的指针,指针类型为
FILE*
➡️函数工作原理:
在打开文件的同时,会返回一个FILE*
的指针变量指向该文件,相当于建立了指针和文件的关系,我们后续便可以使用这个指针进行文件的操作
文件打开成功,则返回一个指向此文件信息区的
起始地址
的指针文件打开失败,则返回
NULL
❗此处类似于动态开辟内存
函数,因为存在打开失败的情况,我们不能贸然直接使用返回的指针,我们应要先对返回的指针进行判断
🧇2.fclose 函数
💡fclose
函数的作用: 关闭所操作的文件
函数的参数:
stream
为想要关闭的文件的文件指针
函数的返回值:
int
➡️函数工作原理:
类似于free
的操作,只需要输入文件指针,fclose
便会关闭文件指针指向的文件信息区
成功关闭文件,则会返回
0
关闭失败,则返回
EOF
【即-1
】
🧇3.文件打开使用方式
✨综上: 我们已经了解了文件的打开和关闭的操作函数,接下来让我们看看在使用fopen
函数的时候有什么使用方式
❗其中最常使用的是前三个,我们需要记住哦~
💥特别注意: 要对文件进行操作,一般最开始先打开文件,最后一定要记得关闭文件【即fopen
与fclose
是要搭配来用的,缺一不可】
🧇4. 例子
👉Eg:
🥐Ⅲ.文件的顺序读写
❗以上的输入
/输出
:指的是对文件
进行输入(写入)、输出(读取)
➡️以下为了让大家对上述的函数有更具体地印象,以下内容将成对函数地进行讲解~
❤️fputc 函数
💡fputc
函数的作用: 对文件进行单个字符的写入
函数的参数:
character
为想要写入文件的字符stream
为指向单个字符写入的文件的地址的指针函数的返回类型:
int
➡️函数工作原理:
函数会将输入的字符写入到文件指针指向的文件中
👉示例:
❗特别注意:
每次以
"w"
的打开方式打开文件关闭文件后,下次进入程序再用"w"
的方式打开的话,文件的内容被重置【即上次写入的内容全部清除了】
❤️fgetc 函数
💡fgetc
函数的作用: 读取文件的一个字符内容
函数的参数:
stream
为指向想要读取字符的文件的地址的指针函数的返回类型:
int
➡️函数工作原理:
函数会每次读取文件中的一个字符
返回的是读取的字符的
ASCII
值
❗特别注意:
每次使用
fgetc
函数,读取文件中的一个字符后,文件指针会自动偏移一下,指向下一个字符,方便读取下一个字符
👉示例:
🧡fputs 函数
💡fputs
函数的作用: 向文件内写入字符串
函数的参数:
str
为想要写入的字符串stream
为指向写入字符串的文件的地址的指针函数的返回值:
int
➡️函数工作原理:
函数会将输入的字符写入到文件指针指向的文件中
👉示例:
🧡fgets 函数
💡fgets
函数的作用: 读取文件中的字符串
函数的参数:
str
为将从文件中读取的字符串,拷贝到str
指向的空间中【一般为数组】num
为读取字符串的个数stream
为指向想要读取文件的地址的指针函数的返回值:
char*
➡️函数工作原理:
函数将会读取文件中
num
个字符个数的字符串
❗特别注意:
1️⃣实际读取的字符个数的字符串会比
num
少一个【因为需要预留一个位置给函数放\0
到str
中】2️⃣读取的过程类似于
fgetc
,文件指针一直在随着读取的字符往后走,本次读取过的就不能在读取了,只能往后读取
👉示例:
💛fprintf 函数
💡fprintf
函数的作用: 将格式化变量的数据写入文件
函数的参数:
stream
为指向写入格式化数据的文件的地址的指针format
为写入数据的格式【Eg:%s
、%d
……】...
为数据的来源函数的返回值:
int
➡️函数工作原理:
函数将格式化数据写入到文件中
❗此处我们可以对比print
函数:
此处我们不难发现:
printf
与fprintf
之间有两个参数是一样的,这样我们也就更好理解什么是格式化数据
了,我们只要回想一下我们平时如何用printf
输出变量的数据就知道了
👉示例:
💛fscanf 函数
💡fscanf
函数的作用: 格式化的方式读取文件中的数据
函数的参数:
stream
为指向格式化方式读取数据的文件的地址的指针format
为读取数据的格式【Eg:%s
、%d
……】...
为格式化数据写入的地方函数的返回值:
int
➡️函数工作原理:
函数将以格式化的方式读取文件中的数据
👉示例:
🫓 总结
✨综上: 就是适用于所有输入、输出流
对文件进行文本的输入、输出操作函数啦~
➡️简单来说: 就是对文件进行文本的输入、输出
💚fwrite 函数
💡fwrite
函数的作用: 对文件进行二进制的写入数据
函数的参数:
ptr
为指向存储要写入到文件的数据的指针size
为要写入的数据的总大小【单位:字节
】count
为最多写几个size
大小为单位的数据【单位:字节
】stream
为指向写入数据的文件的地址的指针函数的返回值:
size_t
➡️函数工作原理:
函数将每次以
count
大小个字节,从ptr
中拿取数据以二进制的方式写入文件中,一共写入size
个字节
👉示例:
💥特别注意:
这里的
fwrite
函数的第三个参数count
为1
是因为前面size
是计算整个结构体的大小,即以整个结构体为单位,所以这里1
的意思是最多
只写入一个这样整个结构体大小的数据
❗实际上10
和5.5f
已经以二进制的方式写入到文本,只是文本的格式显示不出来,所以才显示乱码
💚fread 函数
💡fread
函数的作用: 对文件进行二进制的读取数据
函数的参数:
ptr
为指向要读取的文件的数据的指针函数的返回值:
size_t
➡️函数工作原理:
函数将每次以
count
大小个字节,读取文件中的二进制数据到ptr
所指向的空间,一共读取size
字节
👉示例:
🫓 总结
✨综上: 就是适用于文件输入、输出流
对文件进行二进制的输入、输出操作函数啦~
➡️简单来说: 就是对文件进行二进制的输入、输出
💙sprintf 函数
💡sprintf
函数的作用: 把一个格式化的数据写到一个字符串里
函数的参数:
stream
为指向将格式化数据写入到字符串的地址的指针format
为写入数据的格式【Eg:%s
、%d
……】...
为数据的来源函数的返回值:
int
➡️简单来说:
就是将格式化数据转换成字符串的格式进行打印、输出
👉示例:
💙sscanf 函数
💡sscanf
函数的作用: 把一个字符串读出一个格式化的数据
函数的参数:
stream
为指向存储字符串的地址的指针format
为写入数据的格式【Eg:%s
、%d
……】...
为格式化数据写入的地方函数的返回值:
int
➡️简单来说:
就是将字符串中的数据以格式化的方式读取出来
👉示例:
🫓 总结
✨综上: 就是数据在格式化形式
与字符串形式
之间的转换啦~
➡️简单来说: 上述的函数对比于printf
和scanf
都多了个s
,这个s
的意思就是string
,证明上述的函数都是对字符串进行转换啦~
🥐Ⅳ.文件的随机读写
💜fseek 函数
💡fseek
函数的作用: 根据文件指针的位置和偏移量来定位文件指针
函数的参数:
stream
为指向文件的地址的指针offset
为文件指针的偏移量origin
为文件指针偏移量的相对起始地址函数的返回值:
int
➡️函数工作原理:
函数将会使文件指针在选定的起始位置
origin
处偏移offset
个位置,到达外面想让文件指针到达的位置进行访问
❗C 语言提供了三个origin
(起始位置):
1️⃣
SEEK_SET
:“文件的起始位置处” 开始偏移2️⃣
SEEK_CUR
:“当前文件指针的位置” 开始偏移3️⃣
SEEk_END
:“文件末尾处” 开始偏移
👉示例:
🤎ftell 函数
💡ftell
函数的作用: 返回文件指针相对于起始位置的偏移量
函数的参数:
stream
为指向文件的地址的指针函数的返回值:
int
➡️函数工作原理:
函数将会返回现在文件指针相对于文件的起始位置的偏移量
👉示例:
🖤rewind 函数
💡rewind
函数的作用: 让文件指针的位置回到文件的起始位置
函数的参数:
stream
为指向文件的地址的指针函数的返回值:
void
➡️函数工作原理:
将文件指针的位置重置
👉示例:
🫓 总结
✨综上: 就是可以让文件指针进行随机读取的函数啦~
➡️简单来说: 有了上述函数,就可以让文件指针想读哪里就读哪~
🍞三.文本文件和二进制文件
💡简单来说:
数据在内存中以
二进制
的形式存储,如果不加转换的输出,就是二进制文件
如果加以
ASCII
字符的形式转换,那存储的文件就是文本文件
❗特别注意:
1️⃣
字符
使一律以ASCII
形式存储【这也是为什么上述我们讲的二进制读取和文本读取字符的效果一样】2️⃣
数值型
数据既可以用ASCII
形式存储,也可以使用二进制
形式存储
👉Eg: 如有整数 10000
如果以
ASCII
码的形式输出到磁盘,则磁盘中占用5
个字节(每个字符一个字节)二进制
形式输出,则在磁盘上只占4
个字节
🍞四.文件读取结束的判定
🥐Ⅰ.feof 函数
💡feof
函数的作用: 判断文件结束的时候是否是因为遇到文件尾结束
函数的参数:
stream
为指向文件的地址的指针函数的返回值:
int
➡️函数工作原理:
1️⃣若文件结束时因为遇到文件尾结束的,则返回
非0
值2️⃣若文件结束不是因为遇到文件尾结束的,则返回
0
👉简单来说:
feof
就是文件结束的前提下,判断文件时因为读取失败而结束的,还是遇到文件尾结束
❗特别注意:
1️⃣
feof
只能判断是哪种原因结束的,但不能用来判断文件是否结束【因为这个是feof
使用的前提,不能作为结论来使用】
💥文件读取
是否结束,我们根据如下来判断:
1️⃣文本文件:
①
fgetc
在读取结束时,返回EOF
②
fgets
在读取结束时,返回NULL
2️⃣二进制文件:
①
fread
在读取结束时,返回一个小于实际要读的个数
的值
✨综上:
feof
就是判断文件结束是不是因为上述的三个结束标志造成的
🍞五.文件缓冲区
💡什么是文件缓冲区:
所谓
缓冲文件系统
是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”
❗特别注意:
1️⃣即从内存向磁盘
输出
数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上2️⃣如果从磁盘向计算机
读入
数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)3️⃣缓冲区的
大小
根据C编译系统
决定的。
✨综上:
因为有缓冲区的存在,C 语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件,才能对文件读写正常
否则,如果不做,可能导致读写文件的问题
🫓总结
综上,我们基本了解了 C 语言中的“文件操作”:lollipop:的知识啦~~
恭喜你的内功又双叒叕得到了提高!!!
感谢你们的阅读:satisfied:
后续还会继续更新:heartbeat:,欢迎持续关注:pushpin:哟~
:dizzy:如果有错误❌,欢迎指正呀:dizzy:
:sparkles:如果觉得收获满满,可以点点赞👍支持一下哟~:sparkles:
版权声明: 本文为 InfoQ 作者【Dream-Y.ocean】的原创文章。
原文链接:【http://xie.infoq.cn/article/bccfc45329062b8a253a3db91】。未经作者许可,禁止转载。
评论