C语言 | 文件操作详解与实战示例

🧩 C语言 | 文件操作详解与实战示例

✍️ 作者 :凡间的八戒

🗓️ 时间 :2025-11-12

🏷️ 标签:C语言、文件操作、IO流、fopen、fread、feof、ferror


🧠 前言

在 C 语言学习中,"文件操作"是非常关键的部分。

它赋予程序数据持久化的能力,让我们从屏幕输入输出走向真实的数据存储。

本文将带你全面掌握文件操作的核心内容,包含:

  • 文件概念与类型
  • 打开与关闭
  • 文本与二进制存储方式
  • 顺序/随机读写
  • 缓冲区机制
  • feof 与 ferror 的区别(重点)

一、为什么使用文件?

内存中的数据是临时的 ,程序退出后会被清除。

若想让数据长期保存,就必须将其写入磁盘文件

📘 例如:

  • 游戏存档
  • 程序日志
  • 用户配置

这些都是通过文件实现数据持久化的典型场景。


二、什么是文件?

在程序设计中,文件分为两类:

类型 说明
程序文件 存放源代码(.c)、目标文件(.obj)、可执行文件(.exe)
数据文件 存放程序运行时需要读写的数据

三、文本文件与二进制文件

文件类型 存储形式 可读性 示例
文本文件 ASCII 编码 可直接阅读 .txt
二进制文件 内存原始格式 不可直接阅读 .bin

📘 示例:

c 复制代码
#include <stdio.h>

int main() {
    int a = 10000;
    FILE* pf = fopen("test.txt", "wb");
    fwrite(&a, 4, 1, pf); // 二进制写入
    fclose(pf);
    return 0;
}

四、文件的打开与关闭

打开与关闭函数

c 复制代码
FILE* fopen(const char* filename, const char* mode);
int fclose(FILE* stream);

打开模式速查表

模式 含义 文件不存在时
"r" 只读文本 出错
"w" 只写文本 新建
"a" 追加写文本 新建
"rb" 只读二进制 出错
"wb" 只写二进制 新建
"ab" 追加二进制 新建
"r+" 读写文本 出错
"w+" 读写文本(重建) 新建

📘 示例:

c 复制代码
#include <stdio.h>
int main() {
    FILE* pFile = fopen("myfile.txt", "w");
    if (pFile != NULL) {
        fputs("fopen example", pFile);
        fclose(pFile);
    }
    return 0;
}

五、文件的顺序读写

函数 功能
fgetc 读取单个字符
fputc 写入单个字符
fgets 读取一行
fputs 写入一行
fscanf 格式化读取
fprintf 格式化输出
fread 二进制读取
fwrite 二进制写入

📘 这些函数既可用于文件,也可用于标准流(stdin/stdout)。


六、文件的随机读写

fseek:移动文件指针

c 复制代码
fseek(FILE* stream, long offset, int origin);

ftell:返回当前位置

c 复制代码
long ftell(FILE* stream);

rewind:返回文件头

c 复制代码
rewind(FILE* stream);

📘 示例:

c 复制代码
#include <stdio.h>
int main() {
    FILE* pFile = fopen("example.txt", "wb");
    fputs("This is an apple.", pFile);
    fseek(pFile, 9, SEEK_SET);
    fputs(" sam", pFile);
    fclose(pFile);
    return 0;
}

七、文件读取结束的判断(重点)

在文件操作中,经常要判断文件是否读取完毕或发生错误。

这就需要使用 feof()ferror() ------ 它们看似相似,实则完全不同!


🧩 点击展开 | feof() 与 ferror() 的区别详解

🔹 feof ------ 判断是否到达文件末尾

c 复制代码
int feof(FILE *stream);
  • 上一次读操作到达文件结尾时返回非0。
  • 必须先读取再判断,否则不会触发。

📘 错误示例:

c 复制代码
while (!feof(fp)) { // ❌ 会多读一次
    fscanf(fp, "%d", &x);
    printf("%d\n", x);
}

📘 正确写法:

c 复制代码
while (fscanf(fp, "%d", &x) == 1)
    printf("%d\n", x);

if (feof(fp))
    printf("文件读取完毕\n");

🔹 ferror ------ 判断是否发生读写错误

c 复制代码
int ferror(FILE *stream);
  • 当发生 磁盘错误、权限不足或设备异常 时返回非0。

📘 示例:

c 复制代码
FILE* fp = fopen("test.txt", "r");
if (!fp) {
    perror("打开失败");
    return 1;
}

int c;
while ((c = fgetc(fp)) != EOF)
    putchar(c);

if (ferror(fp))
    puts("❌ 文件读写错误!");
else if (feof(fp))
    puts("✅ 文件正常结束。");

fclose(fp);

🔹 区别总结表

函数 判断内容 触发时机 用途 是否自动清除
feof 到达文件尾 读到EOF后 判断读取结束
ferror 发生错误 I/O异常后 判断设备问题

📘 可使用:

c 复制代码
clearerr(FILE* stream);

清除错误与EOF状态。


🔹 对比示例

c 复制代码
#include <stdio.h>
int main(void) {
    FILE* fp = fopen("demo.txt", "r");
    if (!fp) {
        perror("文件打开失败");
        return 1;
    }

    int c;
    while ((c = fgetc(fp)) != EOF)
        putchar(c);

    if (ferror(fp))
        printf("读取错误!\n");
    else if (feof(fp))
        printf("文件读取完毕。\n");

    fclose(fp);
    return 0;
}

🧠 总结一句话:

feof() 判断文件是否读完;

ferror() 判断是否出错;

二者互不替代,千万别混淆!


八、文件缓冲区机制

C语言使用缓冲文件系统 来提升读写性能。

写入时数据先进入缓冲区,待缓冲满或 fflush() / fclose() 调用后才真正写入磁盘。

📘 示例:

c 复制代码
#include <stdio.h>
#include <windows.h>

int main() {
    FILE* pf = fopen("test.txt", "w");
    fputs("abcdef", pf);
    printf("睡眠10秒,此时文件内容未写入。\n");
    Sleep(10000);
    fflush(pf);
    printf("刷新缓冲区后写入成功。\n");
    fclose(pf);
    return 0;
}

九、总结与学习建议

核心要点:

  • 文件操作基本步骤:fopen → 读写 → fclose
  • 文本与二进制的本质区别在于存储形式
  • 判断结束不要直接用 feof()
  • 养成使用 fflush()fclose() 的好习惯

💡 建议练习:

  1. 设计一个"学生成绩保存系统";
  2. fseek() 实现随机修改;
  3. 手动触发 I/O 错误测试 ferror()
相关推荐
njsgcs2 小时前
excel提取长宽,进行排版导出ezdxf 装箱算法 贪婪 总利用率91%
开发语言·python·excel
雨落在了我的手上2 小时前
C语言入门(十六):指针(2)
c语言
lsx2024062 小时前
Memcached stats sizes 命令详解
开发语言
吃不饱的得可可2 小时前
C++17常用新特性
开发语言·c++
西游音月2 小时前
(4)框架搭建:Qt实战项目之主窗体介绍
开发语言·qt
leo__5202 小时前
MATLAB实现图像超分辨率方法
开发语言·matlab
say_fall2 小时前
C语言编程实战:每日刷题 - day 1
c语言·开发语言·学习
没有bug.的程序员2 小时前
Spring Cloud Bus 事件广播机制
java·开发语言·spring boot·hystrix·feign·springcloudbus·事件广播机制