C语言文件:文件操作完全指南
文件操作使程序能够持久保存数据,是实现信息长期存储的关键。本文将系统讲解文件的分类、打开与关闭、顺序读写、随机读写、文件结束判定以及缓冲区机制,帮助读者掌握C语言文件处理的核心方法。
目录
一、为什么使用文件
程序运行时的数据存储在内存中,程序退出后内存释放,数据即丢失。要实现数据持久化保存,必须将数据写入磁盘文件。文件操作使得数据在程序多次运行间保持可用。
二、什么是文件
文件分为两大类:
- 程序文件 :包含
.c源文件、.obj目标文件、.exe可执行文件。 - 数据文件:程序运行时读写的数据文件,如存储配置、日志、用户数据等。
本讲主要讨论数据文件。
文件名
文件名由三部分组成:文件路径 + 文件名主干 + 文件后缀,例如 c:\code\test.txt。
三、二进制文件和文本文件

根据数据存储形式分类:
- 二进制文件 :数据以内存中的二进制形式直接存储。例如整数
10000占4字节。 - 文本文件 :数据以ASCII码形式存储。例如整数
10000转为字符'1' '0' '0' '0' '0',占5字节。
c
// 以二进制写入整数
int a = 10000;
FILE* pf = fopen("test.bin", "wb");
fwrite(&a, 4, 1, pf);
fclose(pf);
四、文件的打开和关闭
4.1 流和标准流
- 流:抽象概念,表示数据输入输出的通道,程序员通过流操作各种设备。
- 标准流 :C程序启动时默认打开三个流:
stdin(标准输入流,通常对应键盘)stdout(标准输出流,通常对应屏幕)stderr(标准错误流,通常对应屏幕)
4.2 文件指针
每个打开的文件在内存中有一个 FILE 结构体变量,存放文件信息。我们通过 FILE* 指针操作文件。
c
FILE* pf; // 文件指针变量
4.3 文件打开与关闭
fopen:打开文件,返回FILE*指针。fclose:关闭文件,释放资源。
c
FILE* pf = fopen("myfile.txt", "w"); // 以只写方式打开文本文件
if (pf != NULL) {
fputs("hello", pf);
fclose(pf);
}
常用打开模式:
| 模式 | 含义 |
|---|---|
"r" |
只读,文件必须存在 |
"w" |
只写,文件不存在则创建 |
"a" |
追加,文件不存在则创建 |
"rb" |
二进制只读 |
"wb" |
二进制只写 |
"r+" |
读写,文件必须存在 |
"w+" |
读写,不存在则创建 |
注意 :文件操作完成后必须调用 fclose 关闭文件。
五、文件的顺序读写
| 函数 | 功能 | 适用流类型 |
|---|---|---|
fgetc |
读一个字符 | 所有输入流 |
fputc |
写一个字符 | 所有输出流 |
fgets |
读一行字符串 | 所有输入流 |
fputs |
写一行字符串 | 所有输出流 |
fscanf |
格式化读取 | 所有输入流 |
fprintf |
格式化写入 | 所有输出流 |
fread |
二进制读取 | 文件输入流 |
fwrite |
二进制写入 | 文件输出流 |
对比 scanf/printf 与 fscanf/fprintf
scanf默认从stdin读取,printf默认输出到stdout。fscanf可从任意输入流读取,fprintf可向任意输出流写入。
c
// 示例:从文件读取整数并打印
FILE* pf = fopen("data.txt", "r");
int n;
fscanf(pf, "%d", &n);
printf("%d\n", n);
fclose(pf);
六、文件的随机读写
6.1 fseek:移动文件指针
c
int fseek(FILE* stream, long offset, int origin);
origin取值:SEEK_SET:文件开头SEEK_CUR:当前位置SEEK_END:文件末尾
c
fseek(pf, 9, SEEK_SET); // 从开头偏移9字节
fputs("sam", pf); // 覆盖写入
6.2 ftell:获取当前偏移量
c
long pos = ftell(pf); // 返回从文件开头到当前指针的字节数
6.3 rewind:重置文件指针到开头
c
rewind(pf); // 等价于 fseek(pf, 0, SEEK_SET);
七、文件读取结束的判定

重要 :不能直接用 feof 判断文件是否结束,而是应在读取操作后,用 feof 判断结束原因是否为遇到文件尾。
文本文件读取循环
c
int c;
while ((c = fgetc(fp)) != EOF) { // 判断是否结束
putchar(c);
}
if (feof(fp))
printf("正常到达文件末尾\n");
else if (ferror(fp))
printf("读取错误\n");
二进制文件读取循环
c
double b[5];
size_t ret = fread(b, sizeof(double), 5, fp);
if (ret == 5) {
// 成功读取
} else {
if (feof(fp)) printf("文件提前结束\n");
else if (ferror(fp)) printf("读取错误\n");
}
八、文件缓冲区
ANSIC 采用缓冲文件系统,系统为每个文件在内存中开辟一个缓冲区。
- 输出时:数据先写入缓冲区,缓冲区满后才真正写入磁盘。
- 输入时:从磁盘读取数据到缓冲区,再从缓冲区逐个送入程序。
刷新缓冲区 :使用 fflush(fp) 强制将缓冲区内容写入磁盘;fclose 也会自动刷新缓冲区。
c
FILE* pf = fopen("test.txt", "w");
fputs("abcdef", pf); // 数据仍在缓冲区
fflush(pf); // 刷新到磁盘
fclose(pf); // 自动刷新
结论:操作文件后应正确关闭或刷新缓冲区,避免数据丢失。
总结:文件操作实现了数据的持久化存储。通过
fopen/fclose管理文件生命周期,使用顺序读写函数(fgetc/fputc/fgets/fputs/fscanf/fprintf/fread/fwrite)或随机读写函数(fseek/ftell/rewind)进行数据访问。正确判断文件结束(结合feof与ferror)和理解缓冲区机制,是编写可靠文件处理程序的基础。