问题历史:
在C语言中处理文件是基本技能,早在语言的早期实现中就已出现。C标准库(stdio.h)提供了用于输入输出流的通用函数,使程序可以在不同操作系统之间移植。
问题:
初学者在处理文件流时常常犯错误:不检查打开文件的结果,错误管理缓冲的内存,不处理读或写时的错误。关闭文件时的错误会导致资源泄露,不正确处理缓冲可能导致数据丢失。
解决方案:
为了正确处理文件,应始终:
fopen 打开文件;fread、fwrite、fscanf、fprintf 函数进行读取/写入;fclose 关闭文件。代码示例:
#include <stdio.h> int main() { FILE *fp = fopen("example.txt", "w"); if (!fp) { perror("无法打开文件"); return 1; } fprintf(fp, "Hello, world! "); fclose(fp); fp = fopen("example.txt", "r"); if (!fp) { perror("打开文件以便读取时出错"); return 1; } char buffer[100]; while (fgets(buffer, sizeof(buffer), fp)) { printf("%s", buffer); } fclose(fp); return 0; }
关键特性:
可以多次使用 fclose 关闭一个文件吗?
不能,双重关闭文件流会导致未定义行为(undefined behavior)。在 fclose 之后,描述符变得无效。
如果 fread 达到文件末尾,它会返回什么?
fread 返回成功读取的元素数量。如果到达文件末尾,则返回的数量可能少于预期。始终需要检查 feof 和 ferror 以进行诊断。
可以同时使用同一个文件流进行写入和读取吗?
可以,如果文件以 "r+" 或 "w+" 模式打开,但在改变方向(写入/读取)之前必须调用 fflush 或其他文件位置移动操作(fseek)。否则行为未定义。
fclose 之后使用同一个 FILE * 指针。fflush 未调用,流未关闭)。开发者在写入日志文件时没有检查 fopen 的返回值。文件描述符耗尽后,文件不再能够打开——日志信息丢失。
优点:
缺点:
在另一版本的代码中始终检查所有返回值(fopen、fwrite、fclose)。在发生错误时通过 perror 打印详细的诊断信息,并正确结束程序,释放所有资源。
优点:
缺点: