close与fclose有何区别?

99ANYc3cd6
预计阅读时长 15 分钟
位置: 首页 C语言 正文
  • close: 用于关闭文件描述符,是操作系统级别的函数。
  • fclose: 用于关闭文件指针,是C标准库级别的函数。

下面我们通过一个详细的对比表格和解释来彻底搞懂它们。

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

核心概念:文件描述符 vs. 文件指针

要理解 closefclose 的区别,首先必须理解它们操作的对象。

特性 文件描述符 文件指针
层级 操作系统 层级 C标准库 层级
本质 一个非负整数,是内核为了管理一个被打开的文件(或设备、套接字等)而创建的索引。 一个指向 FILE 结构体(在 stdio.h 中定义)的指针
作用域 进程级别的,每个进程都有自己独立的文件描述符表。 C标准库缓冲区的管理。
工作方式 直接与内核交互,进行I/O操作(读、写、等)。 在用户空间维护一个缓冲区,减少与内核的交互次数,提高效率。
如何获取 通过 open(), socket(), pipe() 等系统调用返回。 通过 fopen() 函数返回。
如何关闭 close() fclose()

close() 函数详解

close() 是一个系统调用,直接与操作系统内核交互。

函数原型

#include <unistd.h> // 在 Linux/Unix 系统中
int close(int fd);
  • fd: 要关闭的文件描述符。

功能

  • 释放与文件描述符 fd 相关的系统资源。
  • fd 从当前进程的文件描述符表中移除,这个整数标识符可以被后续的 open() 等系统调用复用。
  • 当进程正常终止时,操作系统会自动关闭该进程打开的所有文件描述符,但显式调用 close() 是一个好习惯,可以立即释放资源。

返回值

  • 成功:返回 0
  • 失败:返回 -1,并设置 errno 来表示具体的错误。

使用场景

  • 主要用于 Linux/Unix 环境下的底层文件操作。
  • 网络编程中关闭套接字 (socket)。
  • 操作管道、设备文件等。

示例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
int main() {
    const char *filepath = "test.txt";
    int fd;
    // 使用 open 系统调用创建/打开文件,返回文件描述符
    fd = open(filepath, O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (fd == -1) {
        perror("open failed");
        exit(EXIT_FAILURE);
    }
    printf("File opened successfully with fd: %d\n", fd);
    // 写入一些数据
    write(fd, "Hello, OS level!", 16);
    // 使用 close 系统调用关闭文件
    if (close(fd) == -1) {
        perror("close failed");
        exit(EXIT_FAILURE);
    }
    printf("File with fd %d closed.\n", fd);
    return 0;
}

fclose() 函数详解

fclose() 是 C 标准库中的一个函数,它位于更高抽象层次。

函数原型

#include <stdio.h>
int fclose(FILE *stream);
  • stream: 指向要关闭的 FILE 对象(即文件指针)的指针。

功能

  • 刷新缓冲区:这是 fclose() 最关键的功能之一,在调用 fclose() 时,它会将 FILE 结构体内部缓冲区中所有尚未写入磁盘的数据强制写入,然后再关闭文件,这可以防止数据丢失。
  • 释放资源:它会调用 close() 系统调用来关闭底层的文件描述符。
  • 释放 FILE 结构体:它会释放 C 标准库为该文件流分配的内存(即 FILE 结构体本身)。

返回值

  • 成功:返回 0
  • 失败:返回 EOF (通常是 -1),并设置 errno

使用场景

  • 绝大多数在 C 语言中进行文件操作的场景(在 Windows、Linux、macOS 上进行可移植的程序开发)。
  • 当你使用 fopen(), fprintf(), fscanf(), fread(), fwrite() 等标准库函数时,你必须使用 fclose() 来对应。

示例

#include <stdio.h>
int main() {
    const char *filepath = "test_stdio.txt";
    FILE *fp;
    // 使用 fopen 标准库函数打开文件,返回文件指针
    fp = fopen(filepath, "w");
    if (fp == NULL) {
        perror("fopen failed");
        return EXIT_FAILURE;
    }
    printf("File opened successfully with FILE pointer: %p\n", (void*)fp);
    // 使用 fprintf 写入数据,数据可能还在缓冲区中
    fprintf(fp, "Hello, C standard library!");
    // 使用 fclose 关闭文件
    // 缓冲区的数据会被写入磁盘,fclose 内部会调用 close()
    if (fclose(fp) == EOF) {
        perror("fclose failed");
        return EXIT_FAILURE;
    }
    printf("File with FILE pointer %p closed.\n", (void*)fp);
    return 0;
}

关系与区别总结

特性 close() fclose()
所属库 操作系统系统调用 (POSIX) C标准库 (stdio.h)
操作对象 文件描述符 (int) 文件指针 (FILE*)
主要目的 告诉内核不再使用该文件描述符 清理C标准库的缓冲区,并最终调用 close()
缓冲区 没有用户空间缓冲区,直接进行I/O。 用户空间缓冲区。fclose()刷新缓冲区。
使用方式 fd = open(...); ...; close(fd); FILE *fp = fopen(...); ...; fclose(fp);
抽象层级 低层,直接与硬件/内核交互 高层,更方便、安全,有缓冲机制
性能 频繁I/O,性能较低 批量I/O,性能较高(因为减少了系统调用次数)

一个绝佳的比喻:银行柜台 vs. ATM

  • fopen()fclose() (C标准库)

    c语言 close fclose
    (图片来源网络,侵删)
    • 你去银行柜台办理业务,银行柜员(FILE 结构体)会给你一个临时的小本子(缓冲区)。
    • 你告诉柜员要存钱、取钱(fprintf, fscanf),柜员先记在小本子上,不会立刻去金库。
    • 当你办完所有业务,对柜员说“结束了”(fclose()),柜员会把小本子上所有的记录一次性处理掉(刷新缓冲区),然后去金库完成真正的操作(调用 close()),最后送走你。
  • open()close() (系统调用)

    • 你直接去金库门口,每次你要存或取钱(read, write),都必须向守卫(操作系统内核)申请开门,完成一笔交易,然后关门,这个过程非常直接,但每次都要和守卫交互,效率较低。

何时使用哪个?

  • 总是优先使用 fopen()/fclose():除非你有特殊需求(如需要精细控制文件权限、进行非标准I/O、或者进行网络编程),否则在C语言中处理文件,都应该使用标准库的 fopen/fclose 系列,它更安全、更高效(因为缓冲)、可移植性更好。
  • 使用 open()/close():当你需要进行底层的、非缓冲的I/O操作时,
    • 网络编程中的 socket
    • 设备驱动编程。
    • 需要使用 open() 的特殊标志(如 O_NONBLOCK 非阻塞模式)。
    • 在性能极端敏感的场景下,手动管理I/O(但这通常不推荐,因为标准库的缓冲机制已经非常优化)。
c语言 close fclose
(图片来源网络,侵删)
-- 展开阅读全文 --
头像
手机端域名如何绑定到m文件夹?
« 上一篇 2025-12-18
dede loop标签如何正确使用?
下一篇 » 2025-12-18

相关文章

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

目录[+]