254

是否有任何理由(除了句法的)你想使用

FILE *fdopen(int fd, const char *mode);

或者

FILE *fopen(const char *path, const char *mode);

代替

int open(const char *pathname, int flags, mode_t mode);

在 Linux 环境中使用 C 时?

4

11 回答 11

268

首先,没有特别好的理由使用fdopeniffopen是一个选项并且open是另一个可能的选择。如果你open想要一个FILE *. 因此,包括fdopen在该列表中是不正确且令人困惑的,因为它与其他列表不太一样。我现在将继续忽略它,因为这里的重要区别在于 C 标准FILE *和特定于操作系统的文件描述符之间。

使用fopen而不是open.

  1. fopen为您提供缓冲 IO,结果可能比您正在使用的open.
  2. fopen如果文件未以二进制模式打开,则行结束翻译,如果您的程序曾经移植到非 Unix 环境,这将非常有用(尽管世界似乎正在​​趋同于仅 LF(IETF 基于文本的网络除外) SMTP 和 HTTP 等协议))。
  3. AFILE *使您能够使用fscanf和其他 stdio 功能。
  4. 您的代码可能有一天需要移植到其他仅支持 ANSI C 而不支持该open功能的平台。

在我看来,行尾翻译更多地阻碍你而不是帮助你,并且解析fscanf非常弱,以至于你不可避免地最终将它扔掉以支持更有用的东西。

并且大多数支持 C 的平台都有一个open功能。

这就留下了缓冲问题。在您主要按顺序读取或写入文件的地方,缓冲支持确实很有帮助,并且大大提高了速度。但这可能会导致一些有趣的问题,即数据不会在您期望它存在时出现在文件中。你必须记住fclosefflush在适当的时候。

如果您正在寻找(又名fsetposfseek第二个以符合标准的方式使用稍微棘手),缓冲的有用性很快就会下降。

当然,我的偏见是我倾向于大量使用套接字,而且事实上你真的想要做非阻塞 IO(它FILE *完全无法以任何合理的方式支持)而根本没有缓冲并且经常有复杂的解析要求真的影响了我的看法。

于 2009-11-01T22:00:49.153 回答
67

open()是一个低级的操作系统调用。fdopen()将 os 级别的文件描述符转换为 C 语言的更高级别的 FILE 抽象。在后台fopen()调用并直接给你一个文件指针。open()

使用 FILE 对象而不是原始文件描述符有几个优点,其中包括更易于使用以及其他技术优势,例如内置缓冲。特别是缓冲通常会带来相当大的性能优势。

于 2009-11-01T21:53:51.720 回答
47

fopen vs 在 C 中打开

1)fopen库函数open而是系统调用

2)fopen提供缓冲 IO ,与非缓冲openIO 相比,它更快。

3)fopen便携而不便携开放是特定于环境的open)。

4)fopen返回一个指向FILE 结构的指针(FILE *)open返回一个标识文件的整数。

5) AFILE *使您能够使用fscanf和其他 stdio 功能。

于 2015-11-26T12:07:54.437 回答
17

除非您是 0.1% 的应用程序的一部分,在这些应用程序中使用open可以带来实际的性能优势,否则确实没有充分的理由不使用fopen. 就fdopen目前而言,如果您不使用文件描述符,则不需要该调用。

坚持使用fopen它的一系列方法(fwrite, fread, fprintf, et al),你会非常满意。同样重要的是,其他程序员会对您的代码感到满意。

于 2009-11-01T21:58:38.393 回答
11

如果您有FILE *,则可以使用fscanf,fprintf等函数fgets。如果您只有文件描述符,则输入和输出例程等有限(但可能更快readwrite

于 2009-11-01T21:53:41.720 回答
7

使用 open、read、write 意味着您必须担心信号交互。

如果调用被信号处理程序中断,函数将返回 -1 并将 errno 设置为 EINTR。

所以关闭文件的正确方法是

while (retval = close(fd), retval == -1 && ernno == EINTR) ;
于 2010-05-05T09:31:08.917 回答
7

open()是一个系统调用,特定于基于 Unix 的系统,它返回一个文件描述符。write()您可以使用另一个系统调用写入文件描述符。
fopen()是一个 ANSI C 函数调用,它返回一个文件指针,它可以移植到其他操作系统。我们可以使用fprintf.

在 Unix 中:
您可以使用以下方法从文件描述符中获取文件指针:

fP = fdopen(fD, "a");

您可以使用以下方法从文件指针中获取文件描述符:

fD = fileno (fP);
于 2015-01-09T02:55:35.130 回答
4

open()将在每个fopen()系列函数的末尾调用。open()是系统调用,fopen()由库作为包装函数提供,方便用户使用

于 2015-01-09T07:03:51.447 回答
2

我为我的应用程序从 fopen() 更改为 open(),因为每次运行 fopen fgetc 时 fopen 都会导致双重读取。双重阅读破坏了我试图完成的事情。open() 似乎只是按照你的要求去做。

于 2012-04-03T19:24:22.213 回答
2

还取决于打开所需的标志。关于写入和读取(以及可移植性)的使用,应使用 f*,如上所述。

但是,如果基本上想要指定的不仅仅是标准标志(如 rw 和附加标志),您将不得不使用特定于平台的 API(如 POSIX open)或抽象这些细节的库。C 标准没有任何此类标志。

例如,您可能想要打开一个文件,只有当它退出时。如果您不指定创建标志,则该文件必须存在。如果你添加独占创建,它只会创建不存在的文件。还有很多。

例如,在 Linux 系统上,有一个通过 sysfs 公开的 LED 接口。它通过文件暴露了led的亮度。将数字写入或读取为 0-255 范围内的字符串。当然,您不想创建该文件,并且仅在它存在时才写入它。现在很酷的事情:使用 fdopen 使用标准调用来读/写这个文件。

于 2016-03-11T10:45:19.523 回答
-1

使用fopen
打开文件 之前,我们可以从(到)磁盘上的文件读取(或写入)信息,我们必须打开文件。打开我们调用函数 fopen 的文件。

1.firstly it searches on the disk the file to be opened.
2.then it loads the file from the disk into a place in memory called buffer.
3.it sets up a character pointer that points to the first character of the buffer.

这种fopen函数的行为方式
在缓冲过程中有一些原因,它可能会超时。所以在比较fopen (high level i/o) 和open (low level i/o) system call 时,它比fopen更快更合适。

于 2014-10-22T16:20:10.697 回答