一、为什么使用文件
程序运行时数据存于内存,程序退出内存回收,数据丢失; 文件可以把数据持久化存储到磁盘,下次运行程序仍可读取历史数据。
二、文件基础概念
1. 文件分类(按功能)
- 程序文件
- 源文件:
.c - 目标文件:Windows 下
.obj - 可执行程序:Windows 下
.exe
- 源文件:
- 数据文件(本章核心讲解对象) 存储程序读写的数据,用来存放输入 / 输出内容,区别于键盘、显示器终端交互。
2. 文件名
完整格式:文件路径 + 文件名主干 + 文件后缀示例:c:\code\test.txt,日常简称文件名。
3. 文本文件 vs 二进制文件(按数据存储形式)
二进制文件内存中二进制数据不做任何转换直接存入外存。 例:int a=10000二进制存储仅占 4 字节。
文本文件数据全部转为 ASCII 字符再存储,数值会拆分成单个字符。 例:int a=10000ASCII 存储占 5 字节('1','0','0','0','0')。
存储规则:字符统一 ASCII 存储;数值ASCll或二进制存储。
三、流、标准流与文件指针
1. 流的概念
我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输⼊输出操作各不相同,为了⽅便程序员对各种设备进⾏⽅便的操作,我们抽象出了流的概念,我们可以把流想象成流淌着字符的河。C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的。
⼀般情况下,我们要想向流⾥写数据,或者从流中读取数据,都是要打开流,然后操作。
2. 三大标准流(程序启动自动打开,无需手动 fopen)
类型均为FILE*(文件指针)
stdin:标准输入流 → 键盘,scanf读取stdout:标准输出流 → 显示器,printf输出stderr:标准错误流 → 显示器,打印错误信息
3. 文件指针 FILE*
打开文件时,系统在内存创建FILE 结构体(文件信息区),存储文件名、读写位置、文件状态等;不同编译器结构体细节略有差异。
FILE* pf:指针指向该 FILE 结构体,通过指针间接操作对应文件。
四、文件打开与关闭
1. 核心函数
- 打开:
FILE* fopen(const char* filename, const char* mode); - 关闭:
int fclose(FILE* stream);
规范:打开文件后必须判断指针是否为 NULL(打开失败);使用完毕必须关闭文件,释放资源 + 刷新缓冲区。
2. 打开模式大全
| 模式 | 类型 | 功能 | 文件不存在时 |
|---|---|---|---|
| r | 文本 | 只读,读取已有文件 | 报错返回 NULL |
| w | 文本 | 只写,清空原有内容写入 | 创建新文件 |
| a | 文本 | 追加,在文件末尾写 | 创建新文件 |
| rb | 二进制 | 只读二进制文件 | 报错 |
| wb | 二进制 | 只写二进制文件 | 创建新文件 |
| ab | 二进制 | 二进制末尾追加 | 创建新文件 |
| r+ | 文本 | 可读可写(原有文件) | 报错 |
| w+ | 文本 | 可读可写(新建清空) | 创建 |
| a+ | 文本 | 可读,末尾追加写 | 创建 |
| rb+ | 二进制 | 二进制读写(原有) | 报错 |
| wb+ | 二进制 | 二进制读写(新建清空) | 创建 |
| ab+ | 二进制 | 二进制可读,末尾追加 | 创建 |
3. 基础示例
如图所示因为要打开的文件就在目前代码所在的路径上面,所以可以只写文件名
int main() { FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } else { printf("打开文件成功"); } return 0; }但如果要打开别的路径上面的文件,就得写全,比如我们想要打开桌面上的text.txt文件
int main() { //绝对路径 FILE* pf = fopen("C:\\Users\\Edbsee\\Desktop\\test.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } else { printf("打开文件成功"); } return 0; }有一种简便写法,如果想要打开的文件不在目前所在代码的路径上,而是在上一级路径,我们可以用.表示,.表示当前路径,..表示上一级路径,如下代码,就是在当前文件所在路径的上一级路径上打开test.txt文件
int main() { FILE* pf = fopen("./../test.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } else { printf("打开文件成功"); } return 0; }最后我们要关闭文件,再让指针指向NULL,避免野指针
int main() { FILE* pf = fopen("./../test.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } else { printf("打开文件成功"); } fclose(pf); pf = NULL; return 0; }