重点
"r"/"w"/"a"等)的选择与使用
fgetc/fputc、fgets/fputs、fread/fwrite)
fseek、ftell、rewind)
难点
feof()的误用(常见错误点)
讲解
互动提问
.c(源代码)、.obj(目标文件)、.exe(可执行文件)
.txt(文本)、.bin(二进制)、.log(日志文件)
C:\code\test.txt
../data/data.txt)
示例
// 打开当前目录下的data.txt文件
FILE *fp = fopen("data.txt", "r");对比
特性 | 文本文件 | 二进制文件 |
|---|---|---|
存储方式 | ASCII字符序列 | 原始二进制数据 |
空间效率 | 较低(如整数10000占5字节) | 更高效(如整数占4字节) |
处理速度 | 较慢(需字符处理) | 更快(直接读写内存) |
典型用途 | 文本数据(日志、配置) | 图像、音频、结构化数据 |
代码示例
// 写入文本文件
FILE *text_fp = fopen("text.txt", "w");
fprintf(text_fp, "10000"); // 写入5个字符
// 写入二进制文件
FILE *bin_fp = fopen("data.bin", "wb");
int num = 10000;
fwrite(&num, sizeof(int), 1, bin_fp); // 写入4字节fopen()FILE *fopen(const char *filename, const char *mode);模式参数:
"r":只读; "w":只写(覆盖); "a":追加
"rb"/"wb":二进制模式
NULL。fclose()int fclose(FILE *stream);0表示成功。
代码示例
FILE *fp = fopen("data.txt", "w");
if (fp == NULL) {
perror("Failed to open file");
exit(EXIT_FAILURE);
}
fclose(fp);函数 | 功能 | 参数示例 |
|---|---|---|
fgetc() | 读取单个字符 | char ch = fgetc(fp); |
fputc() | 写入单个字符 | fputc('A', fp); |
fgets() | 读取一行文本 | fgets(buffer, 100, fp); |
fputs() | 写入字符串 | fputs("Hello", fp); |
函数 | 功能 | 参数示例 |
|---|---|---|
fread() | 读取二进制数据 | fread(buffer, size, count, fp); |
fwrite() | 写入二进制数据 | fwrite(data, sizeof(int), 1, fp); |
练习
fseek():定位文件指针int fseek(FILE *stream, long offset, int whence);SEEK_SET:从文件开头开始
SEEK_CUR:从当前位置开始
ftell():获取当前位置偏移量long ftell(FILE *stream); rewind():重置文件指针到文件开头void rewind(FILE *stream); 示例:修改文件中间数据
// 在二进制文件的第10个字节处写入字符'X'
FILE *fp = fopen("data.bin", "rb+"); // 需要读写权限
if (fp == NULL) {
perror("Failed to open file");
exit(EXIT_FAILURE);
}
// 移动到第10个字节的位置
fseek(fp, 10, SEEK_SET);
fputc('X', fp); // 写入单个字符
fclose(fp); 互动提问
"如何快速获取文件的总大小?"
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
rewind(fp); 常见误区:不要依赖feof()
错误示例:
while (!feof(fp)) {
c = fgetc(fp);
// 处理字符
} 问题:当读取到文件末尾时,feof()会返回true,但此时已经读取了无效的EOF,导致循环多执行一次。
正确方法
文本文件:
fgetc()返回EOF时结束:
while ((c = fgetc(fp)) != EOF) {
// 处理字符
} fgets()返回NULL时结束:
while (fgets(buffer, 100, fp) != NULL) {
// 处理行
} 二进制文件:
fread()返回值小于预期读取的字节数时结束:
size_t elements_read = fread(buffer, sizeof(int), 10, fp);
while (elements_read == 10) {
// 处理数据
elements_read = fread(buffer, sizeof(int), 10, fp);
} 练习
编写一个程序,统计文本文件中的单词数量。
缓冲机制的作用
写操作:数据先写入内存缓冲区,减少磁盘IO次数,提高效率。
读操作:数据从磁盘一次性读入缓冲区,减少频繁访问磁盘的开销。
关键函数
fflush():强制刷新缓冲区
int fflush(FILE *stream); 关闭文件时自动刷新缓冲区:
fclose(fp); // 自动调用fflush(fp) 示例:缓冲区的影响
FILE *fp = fopen("log.txt", "a");
fprintf(fp, "Start processing...\n"); // 数据暂存在缓冲区
// 程序突然崩溃,此时数据可能未写入文件!
fflush(fp); // 显式刷新,确保数据落地 互动讨论
"为什么在多线程程序中需要谨慎使用fflush()?"
(提示:缓冲区竞争可能导致数据不一致)
打开文件(fopen)→ 读写操作 → 关闭文件(fclose)
fopen()返回的文件指针是否为NULL
feof(),改用读取函数的返回值
fflush()确保数据持久化
基础练习
input.txt内容复制到output.txt。
附录:常见错误与调试技巧
"r"模式打开不存在的文件会失败。
fgets()的第二个参数要足够大。