文件open、流fopen、fdopen

本文详细介绍了使用C语言进行文件操作的方法,包括使用fopen、open和fdopen函数打开文件或流的过程,并展示了如何通过fprintf向文件写入数据以及利用fclose确保数据正确地从内存缓冲区刷新到磁盘。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Open打开文件、fopen打开流、fdopen在一个已经打开的文件描述符上打开一个流

   fclose函数关闭文件时,该函数会将保存在内存中尚未来得及写回磁盘的文件内容写到磁盘上。如果没有调用fclose函数,就必须等待内存中缓冲区被填满,由系统将其内容写回到磁盘上去。 

   由于fclose函数在关闭文件时会将缓冲区中的内容写到磁盘上,因此flcose函数实际是进行了一个写文件操作。在网络环境中,文件的内容是要通过网络传输到目的主机上并且写入磁盘的。在这个传输过程中,如果网络连接出现问题或者传输数据出错,就会导致文件内容写入失败。这时fclose函数就会出错。

  1 /* FILE: p662_open.c
  2  * DATE: 20180124
  3  * ==============
  4  * DESCRIPTION: open fopen fdopen
  5  */
  6 
  7 #include <stdio.h>
  8 // #include <unistd.h>  // 宏 STDOUT_FILENO
  9 #include <fcntl.h>
 10 
 11 #define BUFFSIZE 128
 12 
 13 int main(void)
 14 {
 15         FILE *fp;
 16         int fd;
 17         char buf[BUFFSIZE];
 18         int len;
 19         // fopen 打开文件流     
 20         if((fp=fopen("temp.txt", "w")) == NULL)
 21                 perror("fail to fopen");
 22         fprintf(fp, "hello world\n");
 23         fclose(fp);
 24 
 25         // open 打开文件
 26         if((fd=open("temp.txt", O_RDWR)) < 0)
 27                 perror("fail to open");
 28         // fdopen 在已经打开的文件描述符上打开流
 29         if((fp=fdopen(fd, "a")) == NULL)
 30                 perror("fail to fdopen");
 31         fprintf(fp, "hello world again\n");
 32         fclose(fp);
 33 
 34         write(fileno(stdout), "===\n", 5);      // STDOUT_FILENO
 35         fp = fopen("temp.txt", "r");
 36         // 读取文件 并输出
 37         while((len=fread(buf, sizeof(char), BUFFSIZE-1, fp)) > 0)
 38                 fprintf(stdout, "%s", buf);
 39 
 40         return 0;
 41 }



在 C 语言中,`open()` 和 `fopen()` 都是用于**打开文件**的函数,但它们属于不同的 I/O 层次,功能和使用场景也有所不同。 --- ## ✅ 一、基本区别总结 | 特性 | `open()` | `fopen()` | |------|----------|-----------| | 所属标准 | POSIX 系统调用(Unix/Linux) | C 标准库函数(ANSI C) | | 返回类型 | `int`(文件描述符) | `FILE *`(文件指针) | | 缓冲机制 | 无缓冲,直接系统调用 | 有缓冲(默认行缓冲或全缓冲) | | 可移植性 | 不可跨平台(仅适用于 Unix-like) | 可跨平台(C 标准) | | 支持模式 | 通过标志位组合(如 O_RDONLY, O_WRONLY, O_CREAT) | 通过字符串模式(如 `"r"`, `"w"`, `"a"`) | | 权限设置 | 可以设置权限(如 `0666`) | 不支持直接设置权限 | | 文件偏移 | 支持使用 `lseek()` | 不支持 `lseek()`,需用 `fseek()` | --- ## ✅ 二、函数原型 ### 1. `open()`(POSIX 系统调用) ```c #include <fcntl.h> #include <unistd.h> int open(const char *pathname, int flags, ... /* mode_t mode */); ``` - `pathname`:文件路径; - `flags`:打开方式,如 `O_RDONLY`, `O_WRONLY`, `O_CREAT`; - `mode`(可选):文件权限,如 `0666`。 ### 2. `fopen()`(C 标准库函数) ```c #include <stdio.h> FILE *fopen(const char *filename, const char *mode); ``` - `filename`:文件名; - `mode`:打开模式,如 `"r"`, `"w"`, `"a"`,也可加 `b` 表示二进制模式(如 `"rb"`)。 --- ## ✅ 三、使用示例对比 ### 示例 1:使用 `open()` 打开/创建文件 ```c #include <fcntl.h> #include <unistd.h> #include <stdio.h> int main() { int fd = open("test.txt", O_RDWR | O_CREAT, 0666); if (fd == -1) { perror("open"); return -1; } printf("File descriptor: %d\n", fd); close(fd); return 0; } ``` ### 示例 2:使用 `fopen()` 打开/创建文件 ```c #include <stdio.h> int main() { FILE *fp = fopen("test.txt", "w+"); if (fp == NULL) { perror("fopen"); return -1; } printf("File pointer opened.\n"); fclose(fp); return 0; } ``` --- ## ✅ 四、何时使用 `open()`,何时使用 `fopen()`? ### ✅ 使用 `open()` 的场景: - 需要直接与操作系统交互; - 需要设置文件权限; - 需要使用 `mmap()`、`ioctl()`、`select()`、`poll()` 等系统调用; - 需要精确控制文件偏移、非阻塞等; - 多线程或高性能 I/O 操作(如 socket、设备文件); ### ✅ 使用 `fopen()` 的场景: - 简单的文件读写; - 跨平台兼容性要求高; - 不需要控制文件权限; - 使用 `fprintf()`, `fscanf()`, `fgets()` 等高级函数; - 适合初学者或快速开发; --- ## ✅ 五、如何在两者之间转换 ### 1. `int fd` → `FILE *fp`:使用 `fdopen()` ```c FILE *fp = fdopen(fd, "r+"); ``` ### 2. `FILE *fp` → `int fd`:使用 `fileno()` ```c int fd = fileno(fp); ``` --- ## ✅ 六、性能对比(简要) | 操作 | `open()` + `read()`/`write()` | `fopen()` + `fread()`/`fwrite()` | |------|-------------------------------|----------------------------------| | 性能 | 更快(无缓冲) | 稍慢(有缓冲) | | 精度控制 | 更精细 | 更抽象 | | 可移植性 | 差(POSIX) | 好(C 标准) | --- ## ✅ 七、常见错误处理 ### 使用 `open()` 时常见错误: ```c if (fd == -1) { perror("open failed"); // 或者 switch(errno) { case EACCES: printf("Permission denied\n"); break; case ENOENT: printf("File not found\n"); break; // ... } } ``` ### 使用 `fopen()` 时常见错误: ```c if (fp == NULL) { perror("fopen failed"); } ``` --- ## ✅ 小结 | 使用场景 | 推荐方式 | |----------|-----------| | 系统级编程、设备驱动、socket、权限控制 | `open()` | | 应用层文件读写、跨平台程序、快速开发 | `fopen()` | --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值