【C语言程序设计】第34篇:文件的概念与文件指针

发布时间:2026/7/10 0:30:15

【C语言程序设计】第34篇:文件的概念与文件指针 1 引言到目前为止我们所有的程序数据都存储在内存中程序结束后就消失了。但在实际应用中我们需要将数据长期保存比如保存用户配置下次启动时读取记录程序运行日志处理外部数据文件生成报告文档这就需要用到文件操作。C语言通过文件指针和一系列库函数提供了对文件的访问能力。c#include stdio.h int main(void) { FILE *fp; /* 文件指针 */ /* 打开文件 */ fp fopen(test.txt, w); if (fp NULL) { printf(文件打开失败\n); return 1; } /* 写入数据 */ fprintf(fp, Hello, File!\n); /* 关闭文件 */ fclose(fp); return 0; }本章我们将深入理解文件操作背后的概念和机制。2 文件的基本概念2.1 什么是文件文件File是存储在外部介质如磁盘上的数据的集合是程序进行输入输出的基本单位。操作系统以文件为单位管理数据。从程序的角度看文件就是字节序列——一系列可以读取或写入的字节。2.2 文件的分类根据数据的组织形式文件分为两大类文件类型特点示例文本文件以字符为单位每字节存储一个字符的ASCII码.txt,.c,.html二进制文件以字节为单位按内存中的存储形式原样存放.exe,.jpg,.mp32.3 文本文件文本文件存储的是字符序列每个字节对应一个字符的ASCII码。c/* 在文本文件中存储整数 12345 */ fprintf(fp, %d, 12345); /* 实际写入1 2 3 4 5 共5字节 */特点内容可以直接用文本编辑器查看每行通常以换行符结束不同系统换行符不同读写时需要格式转换如数字与字符串的转换占用空间通常比二进制大2.4 二进制文件二进制文件按照数据在内存中的二进制形式原样存储。c/* 在二进制文件中存储整数 12345 */ int n 12345; fwrite(n, sizeof(int), 1, fp); /* 实际写入int 的二进制表示通常4字节 */特点不能用文本编辑器直接查看可能显示乱码读写速度快无需格式转换存储紧凑占用空间小跨平台可能存在字节序问题2.5 文本文件 vs 二进制文件比较维度文本文件二进制文件存储形式字符的ASCII码数据的二进制形式可读性可直接阅读不可直接阅读空间效率较低如数字12345占5字节较高int 12345占4字节读写效率需格式转换较慢直接读写较快换行符处理系统自动转换\n ↔ \r\n不处理原样写入适用场景配置文件、源代码、文档可执行文件、图像、音频3 流的概念3.1 什么是流流Stream是C语言中对输入输出设备的抽象。它提供了一种统一的方式无论数据来自键盘、屏幕、文件还是网络程序都可以用相同的方式读写。text程序 ←→ 流 ←→ 设备文件、键盘、屏幕等3.2 流的分类C语言中的流分为两类流类型说明示例文本流以行为单位处理换行符转换文本文件二进制流字节原样传输不转换二进制文件3.3 标准流当C程序启动时系统会自动打开三个标准流流名称文件指针默认设备用途标准输入stdin键盘读取输入标准输出stdout屏幕输出正常信息标准错误stderr屏幕输出错误信息c#include stdio.h int main(void) { int n; fprintf(stdout, 请输入一个整数); /* 正常输出 */ fscanf(stdin, %d, n); /* 标准输入 */ if (n 0) { fprintf(stderr, 错误输入不能为负数\n); /* 错误输出 */ return 1; } return 0; }4 FILE 结构体与文件指针4.1 FILE 结构体FILE是C语言标准库定义的一个结构体类型用于保存文件的相关信息。它通常包含文件位置指示器当前读写位置缓冲区指针和缓冲区大小文件状态标志是否到达末尾、是否有错误等文件描述符操作系统层面的文件标识c/* 在 stdio.h 中的典型定义简化示意 */ typedef struct { int level; /* 缓冲区填充程度 */ unsigned flags; /* 文件状态标志 */ char fd; /* 文件描述符 */ unsigned char hold; /* 无缓冲区时读取的字符 */ int bsize; /* 缓冲区大小 */ unsigned char *buffer; /* 数据缓冲区 */ unsigned char *curp; /* 当前活动指针 */ unsigned istemp; /* 临时文件标志 */ short token; /* 用于有效性检查 */ } FILE;注意在实际编程中我们不需要关心FILE结构体的内部细节只需要通过FILE*指针使用标准库函数即可。4.2 文件指针文件指针File Pointer是指向FILE结构体的指针用于标识一个流是所有文件操作函数的核心参数。cFILE *fp; /* 定义文件指针 */文件指针的作用标识打开的文件保存文件的状态信息传递给文件操作函数如fprintf、fscanf、fread、fwrite4.3 文件指针与普通指针的区别方面文件指针普通指针指向内容FILE结构体任意类型的数据操作方式通过库函数fread/fwrite等通过解引用*使用者库函数内部维护程序员直接操作5 文件操作的基本流程5.1 三步曲文件操作通常遵循三个步骤打开文件fopen()返回文件指针读写文件fprintf()、fscanf()、fread()、fwrite()等关闭文件fclose()释放资源c#include stdio.h int main(void) { FILE *fp; /* 1. 打开文件 */ fp fopen(example.txt, r); if (fp NULL) { perror(文件打开失败); return 1; } /* 2. 读写文件这里只是示例 */ char buffer[100]; while (fgets(buffer, sizeof(buffer), fp) ! NULL) { printf(%s, buffer); } /* 3. 关闭文件 */ fclose(fp); return 0; }5.2 为什么需要关闭文件关闭文件fclose非常重要原因如下刷新缓冲区确保所有数据真正写入磁盘释放资源释放FILE结构体和系统文件句柄防止数据丢失程序异常结束时缓冲区数据可能丢失c/* 错误忘记关闭文件 */ FILE *fp fopen(data.txt, w); fprintf(fp, 重要数据); /* 程序结束但数据可能还在缓冲区未写入磁盘 */6 文件打开模式fopen的第二个参数指定打开模式常用的有6.1 文本文件模式模式含义文件存在时文件不存在时r只读正常打开返回 NULLw只写内容被清空创建新文件a追加从末尾写入创建新文件r读写正常打开返回 NULLw读写内容被清空创建新文件a读和追加从末尾写入创建新文件6.2 二进制文件模式在文本模式后加b表示二进制模式模式含义rb二进制只读wb二进制只写ab二进制追加rb二进制读写wb二进制读写清空ab二进制读和追加6.3 模式选择示例cFILE *fp; fp fopen(data.txt, r); /* 读取文本文件 */ fp fopen(data.txt, w); /* 写入文本文件覆盖 */ fp fopen(log.txt, a); /* 追加到文本文件末尾 */ fp fopen(image.jpg, rb); /* 读取二进制文件 */ fp fopen(data.bin, wb); /* 写入二进制文件 */7 常见错误与注意事项7.1 忘记检查文件是否成功打开cFILE *fp fopen(nonexistent.txt, r); fprintf(fp, test); /* 如果 fp 为 NULL程序崩溃 */ /* 正确做法 */ FILE *fp fopen(nonexistent.txt, r); if (fp NULL) { perror(打开文件失败); return 1; }7.2 忘记关闭文件cvoid process_file(void) { FILE *fp fopen(data.txt, r); /* 处理文件... */ /* 忘记 fclose(fp) */ } /* 文件句柄泄漏程序运行期间无法再次打开该文件 */7.3 混淆文本模式和二进制模式在 Windows 系统上文本模式下换行符\n会被自动转换为\r\n二进制模式下则不会。c/* 在 Windows 上 */ FILE *fp fopen(test.txt, w); fprintf(fp, Hello\nWorld); /* 实际写入Hello\r\nWorld */ fp fopen(test.bin, wb); fprintf(fp, Hello\nWorld); /* 实际写入Hello\nWorld */7.4 对同一文件进行多次打开同一个文件可以被多次打开每次得到不同的文件指针各自维护独立的位置指示器。cFILE *fp1 fopen(data.txt, r); FILE *fp2 fopen(data.txt, r); fgetc(fp1); /* 读取第一个字符fp1 位置前移 */ fgetc(fp2); /* 也读取第一个字符fp2 位置独立 */7.5 使用已关闭的文件指针cFILE *fp fopen(data.txt, r); fclose(fp); fprintf(fp, test); /* 错误fp 已无效 */7.6 忽略错误处理文件操作可能因各种原因失败磁盘满、权限不足等应该检查返回值cif (fprintf(fp, data) 0) { perror(写入失败); }8 本章小结本章系统介绍了文件的基本概念和文件指针1. 文件的类型文本文件存储字符的ASCII码可直接阅读二进制文件存储数据的二进制形式紧凑高效2. 流的概念程序与设备之间的抽象提供统一接口标准流stdin、stdout、stderr文本流和二进制流的区别3. FILE 结构体与文件指针FILE结构体保存文件的状态信息文件指针是FILE*类型标识一个流程序员只需使用指针不关心内部细节4. 文件操作三步曲fopen()打开文件检查返回值读写操作fclose()关闭文件必须5. 打开模式r只读w写入清空a追加r、w、a读写模式加b表示二进制模式6. 常见错误忘记检查fopen返回值忘记关闭文件混淆文本和二进制模式使用已关闭的文件指针参考资料[1] C语言标准ISO/IEC 9899:2018- 第7.21节文件访问[2] Kernighan, B. W., Ritchie, D. M. (1988). The C Programming Language (2nd ed.). Prentice Hall.[3] Prinz, P., Crawford, T. (2005). C in a Nutshell. OReilly Media.[4] 腾讯云开发者社区. C语言文件操作详解[5] CSDN博客. 文本文件与二进制文件的区别[6] 阿里云开发者社区. FILE结构体深度剖析

相关新闻