C语言文件操作核心指南:打开关闭、读写与缓冲机制详解

月亮慢半拍
月亮慢半拍
发布时间:2026-10-16| 3人浏览过
原创

C语言通过标准IO库实现对硬盘数据的持久化存储。核心流程包括:使用FILE*指针管理文件状态,通过fopen指定模式(读/写/追加等)打开文件,利用fread/fwrite或fprintf/fscanf进行顺序读写,借助fseek实现随机访问,并在结束前务必fclose以刷新缓冲区并释放资源。同时需区分文本与二进制文件,并正确使用EOF与feof判断读取状态。

1. 文件标识与文件名构成

在C语言中,每个文件都必须拥有唯一的标识以便用户引用。文件名由三部分构成:文件路径 + 文件名主干 + 文件后缀。例如 c:\demo\test.txt 中,c:\demo\ 为路径,test 为主干,.txt 为后缀。

2. 文件指针与 FILE 结构体

当文件被打开时,系统会在内存中创建一个名为 FILE 的结构体变量,用于存放文件名、当前读写位置、缓冲区信息等关键数据。开发者通常无需关心 FILE 内部的具体字段,而是通过一个指向该结构的指针变量来进行操作。

定义文件指针变量的语法如下:

FILE *pf;

pf 即为文件信息区的索引,通过它即可访问关联的文件内容。

2.1 文件的打开与关闭

文件在使用前必须打开,使用后必须关闭,以释放资源和保存数据。

  • 打开函数:FILE * fopen ( const char * filename, const char * mode );
  • 关闭函数:int fclose ( FILE * stream );

常见的打开模式包括 r (只读)、w (写入,若存在则清空)、a (追加)、b (二进制模式)等。以下是一个完整的打开-读取-关闭示例:

// 仅展示核心逻辑
FILE* pf = fopen("test.txt", "r");
if (pf == NULL) {
    // 建议打印错误信息以便调试
    printf("%s\n", strerror(errno));
    return -1;
}
// ... 执行文件操作 ...
fclose(pf);
pf = NULL; // 避免悬垂指针

3. 文件的顺序读写

顺序读写是从文件开头到结尾依次进行。根据数据类型和存储格式的不同,主要有以下几种方式。

3.1 字符读写(文本文件)

适用于单个字符的读写。例如实现简单的文件拷贝:

int main() {
    FILE* pr = fopen("data.txt", "r");
    if (!pr) return -1;
    
    FILE* pw = fopen("data2.txt", "w");
    if (!pw) { fclose(pr); return -1; }

    int ch;
    while ((ch = fgetc(pr)) != EOF) {
        fputc(ch, pw);
    }
    
    fclose(pr);
    fclose(pw);
    return 0;
}

3.2 二进制块读写

直接处理内存中的数据块,不经过ASCII转换,效率更高且能保留原始字节结构。常用函数为 fread 和 fwrite。

// 写入二进制结构体数组
struct Stu s[2] = { {"ZhangSan", 20, 95.5}, {"LiSi", 18, 88.0} };
FILE* pf = fopen("data.bin", "wb");
fwrite(s, sizeof(struct Stu), 2, pf);
fclose(pf);

// 读取二进制结构体数组
struct Stu buffer[2] = {0};
FILE* pr = fopen("data.bin", "rb");
fread(buffer, sizeof(struct Stu), 2, pr);
printf("Name: %s Age: %d Score: %.1f\n", buffer[0].name, buffer[0].age, buffer[0].score);
fclose(pr);

3.3 格式化输入输出

类似于 printf/scanf,但针对文件流。例如读取包含姓名、年龄的结构体数据:

struct Stu {
    char name[20];
    int age;
    double score;
};
// 读取示例
FILE* pf = fopen("data.txt", "r");
struct Stu s = {0};
fscanf(pf, "%s %d %lf", s.name, &s.age, &s.score);
fclose(pf);

4. 文件的随机读写

不需要按顺序从头读到尾,可以通过偏移量直接定位到文件的任意位置。

4.1 fseek:定位偏移

原型:int fseek ( FILE * stream, long int offset, int origin );

origin 通常为 SEEK_SET (文件头)、SEEK_CUR (当前位置) 或 SEEK_END (文件尾)。

FILE* pFile;
pFile = fopen("example.txt", "wb");
fputs("This is an apple.", pFile);
fseek(pFile, 9, SEEK_SET); // 定位到第9个字符后
fputs(" sam", pFile);       // 覆盖后续内容
fclose(pFile);

4.2 ftell:获取偏移量

返回当前文件指针相对于文件起始位置的字节偏移量。

long int pos = ftell(pf);

4.3 rewind:复位指针

将文件指针重新定位到文件开头,等效于 fseek(pf, 0, SEEK_SET) 并清除错误标志。

5. 文本文件与二进制文件

区别在于数据在磁盘上的存储形式:

  • 文本文件:数据以 ASCII 码形式存储。例如整数 20000 会存为 '2','0','0','0','0' 五个字节。
  • 二进制文件:数据以二进制补码形式原样存储。整数 20000 仅占 4 个字节。

在使用 fopen 时,加上 b (如 rb, wb) 即进入二进制模式。在 Windows 系统中,Windows 换行符是 \r\n,而 Linux/Mac 是 \n。如果不加 b,系统在读写时会进行自动转换,可能导致二进制数据损坏,因此传输二进制数据时必须使用二进制模式。

6. 正确判断文件读取结束

这是一个常见误区:feof() 不能用来做循环终止条件,它仅在读取操作结束后,判断“是因为遇到文件尾还是因为出错”而结束。

6.1 文本文件判断

检查返回值是否为 EOF (fgetc) 或 NULL (fgets)。

int c;
while ((c = fgetc(fp)) != EOF) {
    putchar(c);
}
// 循环结束后判断原因
if (ferror(fp)) puts("Read Error");
else if (feof(fp)) puts("End of File reached");

6.2 二进制文件判断

检查实际读取的数量是否小于请求数量。

size_t items_read = fread(buffer, size, count, fp);
if (items_read < count) {
    if (feof(fp)) /* 读到末尾 */;
    else /* 发生错误 */;
}

7. 文件缓冲区与 I/O 优化

C 语言的标准 I/O 采用缓冲文件系统。数据写入磁盘并非即时完成,而是先存入内存中的缓冲区,装满后才一次性刷入磁盘。这大大减少了磁盘 IO 次数,提升了性能。

7.1 缓冲区刷新机制

如果你希望数据立刻写入磁盘,可以使用 fflush(FILE*) 强制刷新缓冲区。另外,调用 fclose() 时会自动刷新缓冲区再关闭。

FILE* pf = fopen("test.txt", "w");
fputs("Hello", pf);
// 此时文件可能还未写入磁盘
fflush(pf); // 强制刷盘
fclose(pf);

7.2 缓冲类型

不同来源的流具有不同的默认缓冲策略:

  • 全缓冲 (Full Buffer):通常在文件上启用,缓冲区满才写入磁盘。
  • 行缓冲 (Line Buffer):通常在标准输入输出 (stdin, stdout) 上启用,遇到换行符或缓冲区满时刷新。例如在终端输入命令,输完回车才会执行。
  • 无缓冲 (Unbuffered):如标准错误输出 (stderr),数据直接立即写出,常用于实时日志记录。

综上,在进行 C 语言文件编程时,务必注意打开/关闭配对、二进制模式的正确选择,以及 fclose 对缓冲区刷新的关键作用。

以上就是C语言文件操作的详细内容,更多关于C语言文件读写技巧的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。