C Fopen vs开放


219

您是否有任何其他原因要使用(语法上的除外)

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时?


你是说fdopenopenfopenopen
user7116

您不是说fopen,不是fdopen吗?
09年

9
fopen是标准C库的一部分,open不是。fopen在编写可移植代码时使用。
阿齐兹2009年

是的,我的意思是打开。我刚刚更新了它,但是我认为同样的原理也适用。
LJM

6
@Aziz open是一个POSIX函数。
dreamlax

Answers:


242

首先,没有特别好的理由来使用fdopenif fopen是一个选项,open而另一个是可能的选择。如果您要使用open,则不应该首先使用该文件FILE *。因此,将其包括fdopen在该列表中是不正确且令人困惑的,因为它与其他列表不太相似。我现在将继续忽略它,因为这里的重要区别是C标准FILE *和OS特定的文件描述符之间。

使用fopen而不是的四个主要原因open

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

在我看来,以行结尾的翻译不但不能帮助您,而且常常会给您带来fscanf麻烦,而且对它的解析非常弱,以至于您不可避免地要把它扔掉,而转而使用更有用的东西。

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

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

如果您正在执行搜索(又名fsetposfseek第二种,以符合标准的方式使用起来比较棘手),则缓冲的作用会迅速下降。

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


4
我不会质疑您的经历,但是很想听听您对此的详细说明。对于哪种应用程序,您觉得内置缓冲会妨碍您的工作?到底是什么问题?
Emil H

1
没有看到最后一段。有效点,恕我直言。据我所知,问题是关于文件IO的。
Emil H

7
澄清缓冲的时间。这是您使用搜索的时间。与任何命令下读取(fgetsfgetcfscanffread),总是会读取缓冲区(4K,8K或你设置的)的整体尺寸。通过使用直接I / O,您可以避免这种情况。在这种情况下,最好使用pread而不是查找/读取对(1个系统调用而不是2个)。
PatrickSchlüter,2010年

2
处理中断read()write()调用是使用libc系列函数的便利第五个原因。
nccc 2012年

3
@ m-ric:嗯,这是一个无关紧要的问题,但是可以。所有ioctl支持的平台还支持fileno采用a FILE *并返回可以在ioctl呼叫中使用的号码的呼叫。不过要小心。FILE *相关的调用可能会令人惊讶地与交互,以ioctl用于更改有关基础文件描述符的信息。
全方位2012年

53

open()是低级的os调用。fdopen()将os级文件描述符转换为C语言的高级FILE抽象。在后台fopen()调用open(),并直接为您提供FILE-pointer。

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


3
使用带缓冲的'f ...'版本的open有任何不利之处吗?
LJM

5
@L。Moser,是的,当您已经在缓冲数据时,因此额外的缓冲区会增加不必要的复制和内存开销。
Michael Aaron Safyan 09年

6
实际上还有其他缺点。fopen()打开文件时(例如创建权限,共享模式等)时,不能提供相同级别的控制。通常open(),变体提供了更多的控制权,接近于操作系统实际提供的控制权
Matt Joiner 2009年

2
在极端情况下,您mmap使用正常的I / O进行文件更改并进行更改(听起来确实令人难以置信,实际上是在我们的项目中,并且出于充分的理由),缓冲会成为障碍。
PatrickSchlüter,2010年

您可能还需要使用其他系统功能,例如使用open()通过readahead()将文件预加载到页面缓存中。我想经验法则是“除非绝对需要open(),否则请使用fopen”,open()实际上可以让您做一些花哨的事情(设置/不设置O_ATIME等)。
Tomas Pruzina 2013年

34

fopen vs在C中打开

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

2)fopen提供缓冲IO被更快比较open非缓冲的

3)fopen便携式,而open不是便携式开放是环境的具体)。

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

5)A FILE *使您能够使用fscanf和其他stdio函数。


9
open是POSIX标准,因此非常便于移植
osvein

12

除非您是使用0.1%的应用程序的一部分,使用open会带来实际的性能收益,否则确实没有充分的理由不使用它fopen。就fdopen您而言,如果您不使用文件描述符,则不需要该调用。

坚持使用fopen其的方法家族(fwritefreadfprintf,等),你会很满意。同样重要的是,其他程序员会对您的代码感到满意。


11

如果你有FILE *,你可以像使用功能fscanffprintf以及fgets等,如果你刚才的文件描述符,你有有限的(但可能更快)的输入和输出程序readwrite等等。


7

使用打开,读取,写入意味着您必须担心信号间的干扰。

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

因此,关闭文件的正确方法是

while (retval = close(fd), retval == -1 && ernno == EINTR) ;

4
对于close,这取决于操作系统。在Linux,AIX和某些其他操作系统上执行循环是不正确的。
strcat

另外,使用读取和写入将遇到相同的问题,即,在完全处理输入/输出之前,它们可能会被信号中断,程序员必须处理此类情况,而fread和fwrite则很好地处理了信号中断。
Marcelo '18年

6

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

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

fP = fdopen(fD, "a");

您可以使用以下命令从文件指针获取文件描述符:

fD = fileno (fP);

4

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


2

对于我的应用程序,我从fopen()更改为open(),因为每次我运行fopen fgetc时,fopen都会导致重复读取。重复读取破坏了我要完成的工作。open()似乎可以满足您的要求。


2

还取决于需要打开哪些标志。关于写和读的用法(和可移植性),应该使用f *,如上所述。

但是,如果基本上要指定多个标准标志(例如rw和append标志),则必须使用平台特定的API(例如POSIX open)或抽象这些细节的库。C标准没有任何此类标志。

例如,您可能只想在文件退出时才打开它。如果不指定创建标志,则文件必须存在。如果添加独占创建,它将仅在不存在的情况下创建文件。还有更多。

例如,在Linux系统上,有一个通过sysfs暴露的LED接口。它通过文件显示led的亮度。以介于0到255之间的字符串形式写入或读取数字。当然,您不想创建该文件,仅在存在时才写入该文件。现在很酷:使用fdopen通过标准调用读取/写入此文件。


0

必须先打开文件, 然后才能使用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(高级I / O)与open(低级I / o)系统调用进行比较时,它比fopen更合适。


比打开更快?
obayhan

是的,open是系统调用,它比fopen快-相对于@obayhan
prashad
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.