2、文件的打开与关闭:fopen函数详解、fclose函数详解、文件打开模式

文件操作,说白了就是跟磁盘上的数据打交道。你写程序,数据不能总在内存里待着,一断电就没了。所以得学会怎么打开文件、读写文件、最后关掉它。今天咱们就先把「开门」和「关门」这两件事聊透。

2.1 fopen 函数详解

fopen 是 C 标准库里的一个函数,原型在 <stdio.h> 里。它的作用就是打开一个文件,返回一个文件指针。如果打开失败,返回 NULL。

FILE *fopen(const char *filename, const char *mode);

第一个参数是文件名,可以是相对路径或绝对路径。第二个参数是打开模式,决定了你能对文件做什么操作。

我个人习惯,每次打开文件后都会检查返回值。为什么?因为我在项目里吃过亏。有一次写日志模块,磁盘满了,fopen 返回 NULL,我没检查,后面直接往 NULL 指针里写数据,程序直接崩了。从那以后,我写 fopen 必跟一句:

FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
    perror("文件打开失败");
    return -1;
}

嗯,这步不能省。

2.2 文件打开模式(r/w/a/r+/w+/a+)

打开模式是 fopen 的核心。选错了模式,轻则读不到数据,重则把文件内容清空了。咱们一个一个说。

模式 含义 文件不存在时 文件存在时 文件指针位置
"r" 只读 返回 NULL 正常打开 文件开头
"w" 只写 创建新文件 清空内容 文件开头
"a" 追加 创建新文件 保留内容 文件末尾
"r+" 读写(不创建) 返回 NULL 正常打开 文件开头
"w+" 读写(创建/清空) 创建新文件 清空内容 文件开头
"a+" 读写(追加) 创建新文件 保留内容 文件末尾

重点提醒:

  • "w""w+" 会清空文件内容。如果你只是想修改文件里的某几行,千万别用 "w",否则数据就没了。
  • "a""a+" 只能往文件末尾写,不能往前插。你想想看,日志文件是不是都这样?
  • "r+" 可以读也可以写,但不会创建文件。如果你要打开一个配置文件,用 "r+" 比较安全。

我曾经在项目里犯过一个低级错误:用 "w" 模式打开一个用户数据文件,结果程序一跑,文件被清空了。还好有备份,不然就出大事了。所以我现在写代码,只要不是明确要新建文件,一律用 "r""r+"

2.3 fclose 函数详解

文件用完了,得关掉。fclose 就是干这个的。

int fclose(FILE *stream);

它接受一个文件指针,关闭成功返回 0,失败返回 EOF。为什么一定要关?原因有三:

  • 释放系统资源:每个打开的文件都会占用一个文件描述符。系统资源是有限的,不关的话,开多了就报 "Too many open files"。
  • 刷新缓冲区:fwrite 写数据时,不一定立刻写到磁盘,可能还在缓冲区里。fclose 会强制把缓冲区里的数据刷到磁盘。
  • 防止数据丢失:程序异常退出时,没关闭的文件可能导致数据没写完。fclose 能保证数据完整性。

小技巧:

我习惯在 fopen 之后,紧接着写 fclose 的代码。比如:

FILE *fp = fopen("test.txt", "r");
if (fp == NULL) {
    // 错误处理
}
// ... 读写操作 ...
fclose(fp);

这样就不会忘记关了。你想想看,是不是比写到后面再回头补要靠谱?

注意:

fclose 之后,文件指针就失效了。不要再对 fp 做任何操作。如果你还想用,得重新 fopen。

2.4 知识体系图

下面这张图把文件打开与关闭的核心逻辑串起来了。你可以看到,fopen 是入口,fclose 是出口,中间是各种操作模式的选择。

文件打开与关闭核心流程 开始文件操作 fopen(filename, mode) 返回 FILE* 或 NULL fp == NULL? 错误处理 选择模式:r / w / a / r+ / w+ / a+ fclose(fp) → 结束

这张图里,fopen 是起点,fclose 是终点。中间那个菱形判断,就是检查文件是否打开成功。我建议你把这个流程刻在脑子里,写文件操作代码时,每一步都按这个来。

2.5 完整示例

最后,给你一个完整的例子。它演示了如何用 "w+" 模式创建文件、写入数据、然后关闭。

#include <stdio.h>

int main() {
    FILE *fp = fopen("example.txt", "w+");
    if (fp == NULL) {
        perror("无法打开文件");
        return 1;
    }

    fprintf(fp, "Hello, 文件操作!\n");
    fprintf(fp, "这是第二行。\n");

    fclose(fp);
    printf("文件写入完成。\n");
    return 0;
}

运行之后,你会得到一个 example.txt 文件,里面有两行文字。如果你用 "r" 模式打开一个不存在的文件,fopen 会返回 NULL,程序就会打印错误信息。试试看?

个人经验:

我在做嵌入式项目时,经常需要读写配置文件。那时候我习惯用 "r" 模式先读,如果文件不存在,再用 "w" 创建默认配置。这样既不会误删已有文件,又能处理首次运行的情况。

公众号:蓝海资料掘金营,微信 deep3321