C语言中close与fclose到底有何区别?

99ANYc3cd6
预计阅读时长 15 分钟
位置: 首页 C语言 正文

fclose 是 C 标准库中的一个函数,用于关闭一个之前通过 fopen 打开的文件流。这是一个至关重要的操作,它不仅释放了文件句柄,更重要的是,它会将缓冲区中尚未写入磁盘的数据(脏数据)强制写入文件,并确保所有相关的资源被正确释放。

close fclose c语言
(图片来源网络,侵删)

为什么需要 fclose?—— fopenfclose 的关系

在 C 语言中,对文件的操作通常遵循一个固定的模式:

  1. 打开: 使用 fopen 函数请求操作系统打开一个文件,操作系统会为这个文件分配一些资源,比如一个文件描述符(或句柄)和一个内存缓冲区。fopen 返回一个指向 FILE 结构体的指针,这个指针就是你的“文件句柄”或“流”。
  2. 读写: 使用 fgetc, fgets, fputc, fputs, fread, fwrite, fprintf, fscanf 等函数,通过上一步得到的 FILE 指针对文件进行读写操作。
  3. 关闭: 使用 fclose 函数,告诉操作系统你已经完成了对这个文件的操作,请释放所有为此文件分配的资源。

fclose 的核心作用:

  • 刷新缓冲区: 当你向文件写入数据时,数据通常不会立即写入磁盘,而是先被存放在一个内存缓冲区中,当缓冲区满了,或者程序正常结束时,数据才会被写入。fclose 会强制将缓冲区中所有剩余的数据(无论多少)写入磁盘。如果你不调用 fclose,这些数据可能会丢失!
  • 释放资源: 操作系统能同时打开的文件数量是有限的,每次 fopen 都会消耗一个宝贵的文件句柄。fclose 会把这个句柄归还给系统,供其他程序或本程序的其他文件使用,不关闭文件句柄会导致资源泄露,最终可能导致程序无法再打开新文件。
  • 确保数据完整性: 这是 fclose 最重要的职责,它能保证你的所有写入操作都真正落盘。

fclose 函数详解

函数原型

#include <stdio.h>
int fclose(FILE *stream);

参数

  • stream: 这是一个指向 FILE 结构体的指针,它通常是由 fopen 函数成功调用后返回的指针,这个指针代表了你要关闭的文件流。

返回值

  • 成功: 如果文件成功关闭,fclose 返回 0
  • 失败: 如果在关闭文件过程中发生错误(写入磁盘失败),fclose 会返回 EOF(通常是一个宏,定义为 -1)。

示例代码

#include <stdio.h>
#include <stdlib.h> // 用于 exit()
int main() {
    FILE *fp; // 声明一个文件指针
    char *filename = "my_test_file.txt";
    // 1. 使用 fopen 打开文件
    // "w" 表示以写入模式打开,如果文件不存在则创建,如果存在则清空
    fp = fopen(filename, "w");
    // 检查 fopen 是否成功
    if (fp == NULL) {
        perror("Error opening file"); // perror 会打印出系统错误信息
        return EXIT_FAILURE; // 返回非零表示错误
    }
    // 2. 使用 fprintf 向文件写入数据
    fprintf(fp, "Hello, C Language!\n");
    fprintf(fp, "This is a test for fclose().\n");
    printf("Data has been written to the file (but may still be in buffer).\n");
    // 3. 使用 fclose 关闭文件
    // 这是关键的一步!
    if (fclose(fp) != 0) {
        perror("Error closing file");
        return EXIT_FAILURE;
    }
    // 重要:关闭后,fp 指针不再指向有效的文件流。
    // 一个好的习惯是将指针设为 NULL,防止误用。
    fp = NULL; 
    printf("File has been closed successfully. Data is now guaranteed to be on disk.\n");
    return EXIT_SUCCESS; // 返回 0 表示成功
}

close 函数:系统调用 vs. 库函数 fclose

这是一个非常常见的混淆点。closefclose 都用于关闭文件,但它们属于不同的层面。

特性 fclose (C 标准库函数) close (Unix/Linux 系统调用)
所属 C 标准库 (<stdio.h>) 操作系统内核 (POSIX 标准)
操作对象 FILE* 文件流 (高级抽象) 文件描述符 (整数,如 int fd)
功能 关闭 FILE* 流,刷新缓冲区,释放 FILE 结构体 直接关闭文件描述符,将缓冲区数据同步到磁盘
使用场景 绝大多数情况下都应使用 fclose,它更安全、更方便,处理了所有细节。 在底层系统编程、需要直接与内核交互、或避免标准库开销时使用。
缓冲区 有用户空间缓冲区fwrite/fprintf 的数据先进入标准库的缓冲区,fclose 才刷新它。 没有标准库缓冲区,直接操作内核缓冲区,效率可能更高,但需要程序员自己管理缓冲。
open 的对应 对应 fopen 对应 open (系统调用)

两者之间的关系

fopen 内部其实会调用 open 系统调用。

close fclose c语言
(图片来源网络,侵删)
// 概念上的关系,不是实际代码
FILE* my_fopen(const char* path, const char* mode) {
    int flags = convert_mode_to_flags(mode); // 将 "r", "w" 等转换为 open 的标志
    int fd = open(path, flags, 0666); // 调用 open 系统调用,得到文件描述符
    if (fd == -1) return NULL;
    // 分配一个 FILE 结构体,并关联上这个 fd
    FILE* stream = allocate_and_init_FILE_struct(fd);
    // 设置 FILE 结构体中的缓冲区等
    setup_buffer(stream);
    return stream;
}

fclose 内部则会调用 close 系统调用。

// 概念上的关系
int my_fclose(FILE* stream) {
    // 1. 刷新缓冲区 (这是 fclose 的核心工作)
    flush_buffer(stream);
    // 2. 获取文件描述符
    int fd = get_fd_from_FILE_struct(stream);
    // 3. 调用 close 系统调用
    int result = close(fd); // 关闭文件描述符
    // 4. 释放 FILE 结构体
    free_FILE_struct(stream);
    return result;
}

对于绝大多数 C 语言编程,你应该始终使用 fopenfclose,它们为你提供了高级的、缓冲的、更安全的文件操作接口。close 是一个底层的系统调用,通常只在编写系统程序或需要绕过标准库时才使用。


忘记调用 fclose 的后果

  1. 数据丢失: 这是最严重的后果,如果程序在关闭前崩溃或异常终止,缓冲区中未写入的数据将会永久丢失。
  2. 资源泄露: 每个打开的文件都会消耗一个文件句柄,如果程序循环打开文件但不关闭,最终会达到系统允许打开文件数的上限,导致后续的 fopen 调用失败。
  3. 文件锁定问题: 在某些操作系统上,打开的文件可能会被锁定,其他进程无法访问,只有当文件被关闭后,锁定才会被释放。
函数 功能 关键点
fopen 打开文件,获取 FILE* 流指针 开始文件操作
fclose 关闭 FILE* 流,刷新缓冲区,释放资源 结束文件操作的必经之路,保证数据完整性
close 系统调用,关闭文件描述符 底层操作,通常不直接使用

记住这个黄金法则:fopen,就必须有对应的 fclose,这是一个良好的编程习惯,也是保证程序健壮性的关键。

close fclose c语言
(图片来源网络,侵删)
-- 展开阅读全文 --
头像
织梦getmembername如何获取会员名?
« 上一篇 今天
高端HTML5织梦模板如何助力网站建设?
下一篇 » 今天

相关文章

取消
微信二维码
支付宝二维码

目录[+]