流(是一种类似介质的东西,文件和程序的传输渠道)
- 通用流函数(fgetc/fputc/fgets/fputs/fscanf/fprintf)
它们的参数是 FILE* ,不区分底层是键盘、屏幕还是磁盘文件。
- 传 stdin → 键盘(标准输入流)
- 传 stdout → 屏幕(标准输出流)
- 传 fopen 得到的pf → 磁盘文件(文件流)
函数代码本身完全不用改,只换传入的 FILE* ,读写目标就切换了。
- fread / fwrite:文件专用流函数(只有这两个是只能操作文件的,其他的是程序和文件都能操作)
只能传入磁盘文件的 FILE* ,不能传stdin/stdout,专门做二进制大块读写。
stdin 、 stdout 本质也是FILE类型的流,属于特殊的内置流;
通用流函数接收任意 FILE pf,所以既能操作键盘屏幕,也能操作磁盘文件;
fread/fwrite 设计目标就是读写磁盘上的二进制文件,不支持标准流。
易错点
很多人误以为:流只有磁盘文件。
错误:流是抽象概念。键盘、屏幕、磁盘文件,全部都属于流,只是硬件载体不同。
- 3个默认打开的标准流(程序启动自动创建,不用fopen)
- stdin 标准输入流 → 键盘, scanf 从这里读
- stdout 标准输出流 → 屏幕, printf 往这里写
- stderr 标准错误流 → 屏幕,专门输出报错信息
类型全是 FILE* 文件指针,C语言靠FILE指针管理文件。
- 文件打开模式
模式 类 型 含义 文件不存在时
r 文本只读 读已有文本 报错
w 文本只写 写文本 清空原有内容 创建新文件
a 文本追加 在文件末尾添加 不清原内容 创建新文件
rb 二进制只读 读二进制文件 报错
wb 二进制只写 写二进制 清空旧内容 创建新文件
ab 二进制追加 二进制末尾追加 创建新文件
r+ 文本读写 可读可写,原有文件 报错
w+ 文本读写 新建文件读写,会清空 创建
a+ 文本读写 末尾追加+可读 创建
后缀带 b =二进制;不带b=文本。
⚠易错点: w / wb 打开立刻清空文件原有全部内容,一不小心覆盖数据。
4.基础模板
#include <stdio.h>
int main( )
{
FILE* pf = fopen(“test.txt”, “w”); //打开,前一个是文件名,后一个是方式
if (pf == NULL) // 必须判断是否打开失败!
{
perror(“fopen”);
return 1;
}
// 读写操作…
fclose(pf); //关闭文件
pf = NULL; //置空,野指针风险
return 0;
}
- 章节考点
文本文件:字符按ASCII存储;二进制:内存原样存放。
顺序读写: fgetc/fputc 字符、 fgets/fputs 字符串、 fscanf/fprintf 格式化 读写。
随机读写: fseek (移动文件指针)、 ftell (获取当前位置)、 rewind 回到文件开头。
缓冲区:文件数据不是立刻写硬盘,先放缓冲区, fflush 强制刷新。
(连续2个scanf时会出现这种问题,中间有一个\n)
二级结论&易错点
- r 系列(r、rb、r+)文件不存在直接打开失败;w/a系列不存在就新建。
- a 追加永远在文件末尾写,不能覆盖前面内容。
易错:
忘记判断 fopen 返回值NULL,程序崩溃;
w 模式打开旧文件,直接清空全部数据;
用完不 fclose ,数据留在缓冲区丢失,资源泄漏;
文本和二进制混用,Windows下换行 \n 和 \r\n 转换会踩坑。
- perror(用来找错因)
perror(“打开文件失败”);
perror(“open file”);
perror(“xxx”);
这些写法都成立
7.ftell
人话:查询文件读写光标现在在第几字节位置,返回这个偏移数字
原型:
long ftell(FILE* stream);
搭配 fseek / rewind 演示
FILE* pf = fopen(“bin.txt”,“rb”);
int tmp;
fseek(pf, 8, SEEK_SET); //光标移到第8字节
long pos = ftell(pf); //获取当前光标位置
printf(“%ld\n”, pos); //输出 8
rewind(pf); //光标回到0
pos = ftell(pf);
printf(“%ld\n”, pos); //输出 0
三个函数放一起速记
- fseek:手动移动光标(设置位置)
- ftell:查看光标当前在哪(读取位置)
- rewind:一键把光标挪回文件开头(简化fseek)
431



被折叠的 条评论
为什么被折叠?



