fopen和open 等区别是什么?文件描述符与文件描述指针区别
FILE *fp = fopen(path, "w");
int fd =open(path,)
1.区别
函数 | 定义 | 所属库 | 返回类型 |
---|---|---|---|
fopen | 高级文件操作函数,提供缓冲机制 | 标准 C 库 (stdio.h ) | FILE* (文件指针) |
open | 低级文件操作函数,直接调用系统接口 | Unix/Linux 系统调用 (fcntl.h ) | int (文件描述符) |
(1) 抽象层级
-
fopen
:-
属于 高级 I/O 操作,封装了底层系统调用(如
open
、read
、write
)。 -
提供 缓冲机制(缓冲区的数据可能不会立即写入磁盘,除非显式调用
fflush
或fclose
)。 -
支持格式化输入输出(如
fprintf
、fscanf
)。
-
-
open
:-
属于 低级 I/O 操作,直接与操作系统交互。
-
无缓冲机制:每次
read
/write
都会触发系统调用,数据直接操作硬件。 -
提供更精细的控制(如文件权限、打开模式标志)。
-
(2) 打开模式
-
fopen
:
使用字符串指定模式(如"r"
、"w"
、"a"
、"rb"
等):FILE *fp = fopen("file.txt", "w"); // 写入模式(覆盖)
-
open
:
使用位掩码标志指定模式(如O_RDONLY
、O_WRONLY
、O_CREAT
、O_APPEND
等):int fd = open("file.txt", O_WRONLY | O_CREAT, 0644); // 写入+创建,权限 0644
(3) 错误处理
-
fopen
:-
返回
NULL
表示失败,需通过errno
或perror
获取错误原因:FILE *fp = fopen("file.txt", "r"); if (!fp) { perror("fopen失败"); exit(EXIT_FAILURE); }
-
-
open
:-
返回
-1
表示失败,错误码存储在errno
中:int fd = open("file.txt", O_RDONLY); if (fd == -1) { perror("open失败"); exit(EXIT_FAILURE); }
2. 联系与协作
(1) 从
FILE*
获取文件描述符可以通过
fileno()
函数从FILE*
获取底层文件描述符:FILE *fp = fopen("file.txt", "w"); int fd = fileno(fp); // 获取关联的文件描述符
-
当
fopen
成功时,C标准库会:-
调用底层系统调用(如
open()
)打开文件,获取文件描述符(例如返回3
)。 -
将文件描述符、缓冲区等信息封装到
FILE
结构体中。 -
返回指向该结构的指针(
FILE* fp
)。
-
-
(2) 混合使用场景
-
使用
open
打开文件后,可通过fdopen()
将其转换为FILE*
:int fd = open("file.txt", O_WRONLY); FILE *fp = fdopen(fd, "w"); // 将文件描述符转为FILE*
-
-
3. 典型使用场景
适合 fopen
的场景
-
文本文件读写(如配置文件、日志文件)。
-
需要格式化输入输出(如
fprintf
写入结构化数据)。 -
跨平台开发(标准 C 库接口通用)。
适合 open
的场景
-
需要精细控制文件权限(如设置
O_CREAT
时指定权限掩码)。 -
使用非阻塞 I/O(如
O_NONBLOCK
)。 -
操作特殊文件(如设备文件
/dev
下的节点)。 -
实现文件锁(
fcntl
系统调用需文件描述符)。
文件指针(FILE指针)与文件描述符的区别**:
文件指针:由C标准库提供,类型为`FILE*`,用于高级文件操作(如`fprintf`, `fscanf`等)。
文件描述符:由操作系统提供,类型为整数(如`int`),用于底层系统调用(如`read`, `write`)。
可以使用`fileno()`函数获取文件描述符,例如:`int fd = fileno(fp);`,其中`fp`是`FILE*`类型。
在Linux系统中,可以通过/proc/<pid>/fd
查看进程打开的文件描述符。例如:
# 假设程序PID为1234
ls -l /proc/1234/fd
4. 总结
特性 | fopen | open |
---|---|---|
抽象层级 | 高级(带缓冲) | 低级(无缓冲) |
性能 | 适合批量操作 | 适合实时操作 |
灵活性 | 有限(依赖标准库) | 高(直接控制文件描述符) |
跨平台性 | 强(标准C库) | 弱(依赖Unix/Linux系统) |
典型用途 | 文本处理、格式化I/O | 设备操作、非阻塞I/O、文件锁 |