【C语言】文件I/O的不同方式:文件描述符fd和FILE *

fd(文件描述符)和 FILE *(文件指针)是 C 语言中用于处理文件 I/O 的两种不同机制,分别属于 低层系统调用接口标准库函数接口。它们在使用方式、功能特性和适用场景上有明显区别。


📌 一、基本概念对比

特性fd(文件描述符)FILE *(文件指针)
类型int 类型整数FILE * 指针类型
所属接口POSIX 系统调用(如 Linux/Unix)ANSI C 标准库(stdio.h
示例函数open(), read(), write(), close()fopen(), fread(), fwrite(), fclose()
缓冲机制无缓冲(直接系统调用)有缓冲(性能更好)

1.1 缓冲机制的作用

  • FILE * 的缓冲:C 标准库中的 FILE * 提供了用户空间的缓冲区。当你使用像 fread()fwrite() 这样的函数读写数据时,数据首先被存储到这个缓冲区中。只有当缓冲区满、执行 fflush() 操作、或关闭文件时,这些数据才会一次性地传输到内核空间并最终写入磁盘或其他设备。这种方式减少了实际 I/O 操作的次数,从而提高了效率。

  • fd 的无缓冲:直接使用系统调用如 read()write() 对应的是文件描述符 fd。每次调用都会导致一次从用户空间到内核空间的切换,并且每次调用都可能产生一次实际的 I/O 操作。这种模式下没有额外的用户空间缓冲,所以对于小块数据的频繁读写来说,可能会更慢,因为每次操作都有固定的开销。

1.2 示例说明

假设你需要写入一条日志信息到文件:

  • 使用 fd

    write(fd, "Log message\n", strlen("Log message\n"));
    

    每次调用 write() 都会产生一次系统调用,这对于频繁的日志记录来说开销较大。

  • 使用 FILE *

    fprintf(fp, "Log message\n");
    

    数据首先会被写入用户空间的缓冲区,只有在缓冲区满了或者显式调用 fflush(fp) 时,才会真正触发一次系统调用。这样可以在不影响功能的前提下,大幅减少系统调用的频率。

🧱 二、核心区别详解

1. 抽象层级不同

  • fd 是操作系统层面的 底层接口,直接操作内核提供的文件描述符。
  • FILE * 是 C 标准库对 fd 的封装,提供了更高层次的抽象和缓冲机制。

2. 跨平台性

  • fd:主要用于 Unix/Linux 系统,在 Windows 上不兼容。
  • FILE *:跨平台支持好(Windows、Linux、Mac 都支持),推荐用于可移植代码。

3. 缓冲机制

  • fd:没有缓冲,每次读写都直接访问磁盘或设备,效率较低。
  • FILE *:自带缓冲区,减少实际 I/O 操作次数,提高性能。

4. 功能丰富性

  • FILE * 支持格式化输入输出(如 fprintf, fscanf),而 fd 不支持,只能处理原始字节流。

🛠️ 三、常见函数对照表

操作fd 接口(系统调用)FILE * 接口(标准库)
打开文件open("file.txt", O_RDONLY)fopen("file.txt", "r")
读取数据read(fd, buf, size)fread(buf, 1, size, fp)
写入数据write(fd, buf, size)fwrite(buf, 1, size, fp)
关闭文件close(fd)fclose(fp)
文件定位lseek(fd, offset, SEEK_SET)fseek(fp, offset, SEEK_SET)
获取当前位置lseek(fd, 0, SEEK_CUR)ftell(fp)

🔁 四、如何相互转换?

fd 转换为 FILE *

int fd = open("file.txt", O_RDONLY);
FILE *fp = fdopen(fd, "r");  // 成功后可以用标准库函数读写

FILE * 转换为 fd

FILE *fp = fopen("file.txt", "r");
int fd = fileno(fp);  // 获取对应的文件描述符

🎯 五、适用场景对比

场景推荐使用
需要高性能、直接控制文件偏移fd
需要格式化读写(如文本日志)FILE *
跨平台开发FILE *
嵌入式系统、驱动开发、网络通信fd
需要缓冲优化性能FILE *

✅ 六、示例对比

使用 fd

#include <fcntl.h>
#include <unistd.h>

int fd = open("test.txt", O_WRONLY | O_CREAT, 0644);
const char *msg = "Hello, world!\n";
write(fd, msg, strlen(msg));
close(fd);

使用 FILE *

#include <stdio.h>

FILE *fp = fopen("test.txt", "w");
fprintf(fp, "Hello, world!\n");
fclose(fp);

🧾 总结一句话:

  • fd 是更接近系统的底层接口,适合需要精确控制和高效处理的场景;
  • FILE * 是 C 标准库封装的高层接口,使用简单、功能丰富,适用于大多数应用程序开发;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值