C fopen vs open

LJM*_*LJM 201 c unix linux file-io fopen

您是否有任何理由(语法除外)

FILE *fdopen(int fd, const char *mode);
Run Code Online (Sandbox Code Playgroud)

要么

FILE *fopen(const char *path, const char *mode);
Run Code Online (Sandbox Code Playgroud)

代替

int open(const char *pathname, int flags, mode_t mode);
Run Code Online (Sandbox Code Playgroud)

在Linux环境中使用C时?

Omn*_*ous 230

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

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

  1. fopen为您提供缓冲IO,可能比您正在使用的速度快得多open.
  2. fopen 如果文件没有以二进制模式打开,那么行结束转换,如果你的程序被移植到非Unix环境,这将非常有用.
  3. A FILE *使您能够使用fscanf和其他stdio功能.
  4. 您的代码有一天可能需要移植到仅支持ANSI C并且不支持该open功能的其他平台.

在我看来,结束翻译的行更多地是以你的方式而不是帮助你,并且解析fscanf是如此微弱以至于你不可避免地最终将其抛弃而转而支持更有用的东西.

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

这留下了缓冲问题.在主要是按顺序读取或写入文件的地方,缓冲支持非常有用并且速度大大提高.但它可能会导致一些有趣的问题,当您希望数据存在时,数据不会在文件中结束.你必须记住fclosefflush在适当的时候.

如果你正在进行搜索(也就是说,fsetpos或者fseek第二种方法在符合标准的方式中使用起来有点棘手),缓冲的有用性会迅速降低.

当然,我的偏见是我倾向于使用套接字很多,并且事实上你真的想要做非阻塞IO(FILE *完全不能以任何合理的方式支持)而根本没有缓冲有复杂的解析要求真的为我的感知着色.

  • 澄清缓冲何时妨碍.这是你使用搜索时.以下用任何命令(`fgets`,`fgetc`,`fscanf`,`fread`)读取,将始终读取缓冲区的整个大小(4K,8K或您设置的任何内容).通过使用直接I/O,您可以避免这种情况.在这种情况下,使用`pread`代替搜索/读取对(1个系统调用而不是2个)更好. (7认同)
  • 我不会质疑你的经历,但我很乐意听到你对此有所了解.对于什么样的应用程序,您觉得内置缓冲会妨碍?究竟是什么问题? (4认同)
  • @m-ric:嗯,这是一个有点无关的问题,但是是的.支持`ioctl`的所有平台也支持`fileno`调用,它接受`FILE*`并返回一个可以在`ioctl`调用中使用的数字.但要小心.`FILE*`相关的调用可能与使用`ioctl`改变底层文件描述符的内容有惊人的交互. (3认同)
  • 处理中断的`read()`和`write()`调用是使用libc系列函数的一个方便的第五个原因. (2认同)
  • 我拥有一个地图渲染库(CartoType),它有自己的缓冲。我尝试了从高级 io 转向低级 io(从 fopen 到 open 等),并对前后的性能进行了基准测试。低级 io 更好,但仅提高了 3%。我还没有决定 3% 的改进是否值得。可能是的,因为我可以封装依赖于平台的代码。 (2认同)

Emi*_*l H 50

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

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

  • 实际上还有其他缺点.`fopen()`在打开文件时不提供相同级别的控制,例如创建权限,共享模式等.通常`open()`和变体提供更多控制,接近操作系统实际提供的控制 (6认同)
  • @L.Moser,是的,当你已经在缓冲数据时,额外的缓冲区会增加不必要的复制和内存开销. (5认同)
  • 使用open的'f ...'版本是否有任何缺点? (3认同)
  • 还有一些极端的情况,你会对文件进行"mmap"并使用正常的I/O进行更改(就像我们在项目中实际上那样令人难以置信,并且出于真正的原因),缓冲将会妨碍. (2认同)

Yog*_*H T 28

fopen vs C开放

1)fopen是一个库函数open是一个系统调用.

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

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

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

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

  • `open`是POSIX标准,所以它非常便携 (6认同)
  • *`open` 是一个 **系统调用**。* 呃。我不知道为什么会有这种毫无意义的人为划分。几乎所有现存的 POSIX 系统上的 `open()` 都是一个**库函数**,就像 `fopen()` 一样。`open()` **库函数**通常是围绕`openat` **系统调用**实现的。即便如此,在出现 `openat()` 系统调用之前,`open()` 仍然是一个包裹在 `open()` 系统调用周围的**库函数**。`fopen()` 只是一个更大的库函数包装器,与 `open()` 库函数使用的系统调用相同。 (6认同)

dre*_*lax 11

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


use*_*116 11

除非你是0.1%使用open的实际性能优势的应用程序的一部分,否则没有充分的理由不使用fopen.就fdopen您而言,如果您没有使用文件描述符,则不需要该调用.

与坚持fopen及其系列方法(fwrite,fread,fprintf,等),你会很满意.同样重要的是,其他程序员会对您的代码感到满意.


dig*_*igy 7

使用开放,读取,写入意味着您必须担心信号交互.

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

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

while (retval = close(fd), retval == -1 && ernno == EINTR) ;
Run Code Online (Sandbox Code Playgroud)

  • 对于'close',这取决于操作系统.在Linux,AIX和其他一些操作系统上执行循环是不正确的. (4认同)

小智 6

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


Aru*_*oor 5

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

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

fP = fdopen(fD, "a");
Run Code Online (Sandbox Code Playgroud)

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

fD = fileno (fP);
Run Code Online (Sandbox Code Playgroud)