文件

官方信息技术老师·11 页·深入(追求细节与边界)·0 次浏览·3 天前
C 语言文件 I/O缓冲机制随机读写

文件

从打开到定位:搞懂文件操作的底层逻辑与边界陷阱

按 空格/→ 演示下一步

1 / 11 页

全部页面点击任意一页,跳回舞台从这页播放

C 语言文件 I/O缓冲机制随机读写

文件

从打开到定位:搞懂文件操作的底层逻辑与边界陷阱

1第 1 页 · 文件

文件的基本概念

你在 Word 里写了一篇文章,按下「保存」,弹出一个窗口让你选位置、取名字。这一刻,「文件」这个抽象概念就被创造出来了。

定义
外部存储介质上、有名字的一组相关信息的集合
完整标识
路径+文件名+扩展名才能唯一定位一个文件
元数据
大小、修改时间、权限等描述文件本身的信息
字节视角
操作系统眼里,文件就是一串字节,含义由程序解释
统一抽象
抹平磁盘、U 盘、网络盘等设备的差异
图书馆里的书对应 →文件

书名+索书号定位唯一一本;封面是元数据;纸张内容由读者解读;书架差异被抹平

2第 2 页 · 文件的基本概念

文件的打开和关闭

前页讲了文件是什么——但文件只是躺在磁盘上的字节序列。要真正读写它,第一步就是「打开」。这一步看似只是按个按钮,本质却是让操作系统在内存里建立一条专属通道。

打开=建通道
进程向 OS 申请访问,OS 在内核分配缓冲区、登记权限,建立到磁盘文件的通路
打开模式
r 只读 / w 清空写 / a 追加写 / + 拓展读写,决定后续能对该文件做什么
句柄/描述符
OS 返回的非负整数(如 fd=3),是后续 read/write 调用定位该文件的唯一凭证
关闭=归还
刷新缓冲区到磁盘、释放描述符槽位;漏关会导致数据丢失或句柄耗尽
去图书馆借阅对应 →打开/关闭文件

借书=申请访问并拿到索书号;句柄就是索书号,归还=结束访问释放馆藏

3第 3 页 · 文件的打开和关闭

文件的读写函数

文件打开了,光有个通道没用——真正的工作是把数据从里往外读、或从外往里写。C 语言把读写按颗粒度分成了几档,每档各有适用场景和边界。

字符级读写
fgetc / fputc,一次操作一个字节,适合逐字符处理
字符串级读写
fgets / fputs,一次读一行,遇换行或缓冲区满停止
块级读写
fread / fwrite,按指定字节块搬运,适合二进制与结构体
格式化读写
fprintf / fscanf,按格式串解析,体验贴近 printf/scanf
返回值与 EOF
读到尾或出错返回 EOF / NULL,必须显式检查
读书翻页对应 →文件读写

文件指针像指尖从头移到尾;逐字像 fgetc,逐行像 fgets,整段像 fread

4第 4 页 · 文件的读写函数

文件的定位操作

读写函数会按顺序推进指针,但有时想直接跳到某处——比如读日志末尾最新一条。这就需要定位操作。

fseek()
移动指针到指定位置,参数:流、偏移量、基准点
ftell()
返回当前指针距离文件开头的字节数
rewind()
重置指针到开头,等价于 fseek(fp,0,SEEK_SET)
基准 whence
SEEK_SET 从开头、SEEK_CUR 从当前、SEEK_END 从末尾
文本模式有坑
\r\n 转换会让 ftell 偏移量与实际字节数不一致
音乐播放器进度条对应 →文件定位操作

拖动进度条跳到任意时刻 = fseek;显示当前播放时间 = ftell

5第 5 页 · 文件的定位操作

文件的出错检测

前面学了打开、读写、定位文件——但都假设操作成功。现实中磁盘可能损坏、路径可能写错,读到末尾时返回值还会和出错混淆。出错检测就是给文件操作装上'诊断系统'。

errno
标准库维护的全局错误码,I/O函数失败时设置它,必须立即查看
perror等函数
把errno翻译成可读字符串;perror直接打印,strerror返回字符串
feof与ferror
feof判末尾,ferror判I/O错误;二者配合可区分'读完'与'读失败'
返回值检查
fopen返NULL、fgetc返EOF、fread返0都是异常信号,是最先要看的
汽车仪表盘故障灯对应 →文件出错检测体系

故障灯亮=errno被设置;perror等=查看具体故障图标

6第 6 页 · 文件的出错检测

二级C考点解析之文件基本

在桌面上双击文本文档、看一眼内容、改几个字、保存关闭——C 语言读写文件流程几乎一样,但中间需要一张「通行证」才能让程序操作磁盘上的数据。

文件指针 FILE*
程序与文件的句柄,fopen 返回、fclose 释放,所有读写都围绕它进行
文本 vs 二进制
文本存 ASCII 字符(人类可读),二进制存内存原样字节(紧凑高效)
缓冲机制
数据先暂存内存,达阈值或 fclose 才落盘,减少磁盘 I/O 次数
三步流程
fopen 打开 → fread/fwrite 读写 → fclose 关闭,缺一步可能丢数据
去档案室调阅资料对应 →C语言文件操作

登记领钥匙(FILE*)→桌上翻阅批注(读写)→出门归还钥匙(fclose)

7第 7 页 · 二级C考点解析之文件基本

二级C考点解析之文件读写

二级C考点解析之文件读写操作:定义、要点与典型应用

二级C考点解析之文件读写
二级C考点解析之文件读写操作:定义、要点与典型应用
8第 8 页 · 二级C考点解析之文件读写

二级C考点解析之文件检测

读写文件时,如果读不出来数据,问题出在哪?是文件到头了,还是中间出了故障?二级C里,「文件检测」就是用一组函数告诉程序:这次读不下去,究竟是哪种情况。

fopen成功性检测
调用fopen()之后,必须检查返回值是否为NULL,否则后续操作全部未定义
feof()函数
判断文件流是否到达末尾;必须在读操作失败之后调用才有意义
ferror()函数
判断文件流是否发生读写错误;同样要在读操作失败之后调用
clearerr()函数
手动清除EOF和错误标志,使文件流可以继续后续操作
医生诊断病人对应 →文件检测流程

先确认活着(fopen),失败时区分EOF还是IO错,clearerr清创继续

9第 9 页 · 二级C考点解析之文件检测

本节要点

  • FILE* 是文件操作的唯一入口句柄
  • 文本与二进制模式的差异在换行符转换
  • 定位操作的三种偏移基准容易混淆
  • feof 与 ferror 是事后状态而非预测
  • fclose 隐含 flush,异常退出仍丢数据
延伸主题:文件缓冲区的内部机制二进制文件与结构体直存标准 I/O 与系统调用的关系
10第 10 页 · 本节要点

课后思考

先遮住答案区,自己想 30 秒再看参考答案。

1为什么 fopen 打开文件后必须调用 fclose?操作系统层面到底发生了什么?

参考答案fclose 会把缓冲区内容真正写入磁盘、归还文件描述符。不调用可能导致数据丢失(缓冲未刷新)、文件被锁定、超出进程可同时打开的文件数上限。

2一个 10GB 的日志文件,内存只有 4GB,如何用本章学到的函数只读最后 1000 行?

参考答案用 fseek 移到文件末尾,ftell 取总大小,再反向估算定位,分段读入小块内存逐字符找换行符,直到攒够 1000 行。本质是用定位操作替代一次性加载。

3用 r+ 模式打开文件后,先写后读和先读后写,结果有什么不同?什么时候需要 fflush?

参考答案r+ 下读写共享文件指针。切换方向时不 fseek 调整位置或 fflush 清空缓冲区,可能读不到刚写入的内容。这是文本/二进制模式都要注意的隐藏考点。

11第 11 页 · 课后思考