除了语法上的原因,你还想使用它的任何理由吗?
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语言时需要注意什么?
其中,fdopen
与其他函数不同。如果您先调用了open
,然后想要一个FILE *
时,可以使用fdopen
。如果有选择的话,这样做没有意义,而是直接调用fopen
。可能有一些情况下,fopen
无法完全满足您的需求,但它们超出了本问题的范围。
因此,我们假装fdopen
不存在,并继续提出问题。
使用fopen
而不是open
有四个主要原因。
fopen
提供了缓冲IO,可能比你使用 open
更快。fopen
如果文件没有以二进制模式打开,会进行换行符转换,这在将来将程序移植到非Unix环境时非常有帮助(尽管世界似乎正在趋于仅支持LF的环境,除了IETF的文本协议如SMTP和HTTP等)。FILE *
让你能够使用 fscanf
和其他stdio函数。open
函数的平台。在我看来(并根据我的经验),换行符转换更多时候会妨碍你而不是帮助你,而 fscanf
的解析功能很弱,你最终会选择放弃它,转而使用更实用的方法。
大多数支持C语言的平台都有一个 open
函数。
FILE *
在任何合理的方式上都无法支持)而且通常有复杂的解析要求,这确实影响了我的看法。read()
和write()
调用是使用libc函数族的方便第五个原因。 - ncccioctl
的平台也支持 fileno
调用,它接受一个 FILE *
并返回一个数字,该数字可以用于 ioctl
调用。不过要小心。与 ioctl
更改底层文件描述符相关的 FILE *
相关调用可能会产生意外的交互作用。 - Omnifariousfopen()
在打开文件时无法提供与创建权限、共享模式等相关的同样高级别的控制。通常,open()
和其变种会提供更多的控制,接近于操作系统实际提供的控制水平。 - Matt Joinermmap
将文件映射到内存中,并进行常规 I/O 操作(尽管听起来难以置信,但我们在项目中确实这样做了,而且出于非常好的原因),这时缓冲会成为阻碍。 - Patrick Schlüterfopen
与open
在C语言中的区别
fopen
是一个库函数,而open
是一个系统调用。
fopen
提供缓冲IO,相比之下open
是非缓冲IO,可能更快。
fopen
是可移植的,而open
不是可移植的(open
是环境特定的)。
fopen
返回一个指向FILE
结构体(FILE *
)的指针,而open
返回一个标识文件的整数。
FILE *
使您能够使用fscanf
和其他stdio.h
函数。
fopen()
不是 async-signal-safe(缓冲io都不是),因此它不应该在任何信号处理程序中使用 - 或者在可能被调用的函数中使用,并且如果在使用异步线程的函数中使用,则应该小心。使用 open()
会增加复杂性并且缺少缓冲io... - Simon Sobischfopen()
。还有strcpy()
。以及C语言中可能一半以上所需的函数。现在应该使用_open、_close。 不,你不是“应该使用”。“微软希望你这样做是因为它不具备可移植性”可能更接近实际情况。 - Andrew Henleopenat
系统调用。 - Omnifariousopen
确实可以提高性能,否则没有理由不使用fopen
。至于fdopen
,如果你不涉及文件描述符,就不需要使用这个调用。fopen
及其方法族(如fwrite
、fread
、fprintf
等),你会感到非常满意。同样重要的是,其他程序员也会对你的代码感到满意。open
,因为我不喜欢 const char *mode
而更喜欢 int mode
。 - user16217248如果你有一个FILE *
,你可以使用像fscanf
、fprintf
和fgets
等函数。如果你只有文件描述符,你将拥有受限的(但可能更快)输入输出例程:read
、write
等。
open()
是一个系统调用,仅适用于基于Unix的系统,并返回文件描述符。您可以使用另一个系统调用write()
向文件描述符写入内容。
fopen()
是一个ANSI C函数调用,返回一个文件指针,可在其他操作系统中使用。我们可以使用fprintf
向文件指针写入内容。
在Unix中:
您可以使用以下方法从文件描述符获取文件指针:
fP = fdopen(fD, "a");
fD = fileno (fP);
使用open、read、write等函数需要担心信号中断的问题。
如果调用被信号处理程序中断,那么这些函数将返回-1并设置errno为EINTR。
因此,正确的关闭文件的方法是
while (retval = close(fd), retval == -1 && ernno == EINTR) ;
我在我的应用程序中从fopen()改为使用open(),因为fopen()每次运行fgetc时会导致双重读取。这种双重读取会干扰我想要完成的任务。相比之下,open()似乎只是按照你的要求执行操作。
open()函数会在每个fopen()系列函数的结尾处被调用。 open() 是一个系统调用,而 fopen() 则是由库作为包装函数提供给用户使用的。
具体要看打开文件需要哪些标志。为了写入和读取(以及可移植性),应该使用f*,正如上面所述。
但是,如果基本上想要指定超出标准标志的内容(例如rw和追加标志),则必须使用特定于平台的API(例如POSIX open)或抽象这些细节的库。C标准没有任何这样的标志。
例如,您可能只想打开一个文件,如果存在的话。如果不指定创建标志,则文件必须存在。如果将独占添加到创建中,则仅在文件不存在时才会创建该文件。还有更多其他标志。
例如,在Linux系统上,通过sysfs公开了LED接口。它通过文件公开了LED的亮度。将数字作为字符串从0-255进行写入或读取。当然,您不希望创建该文件,并且仅在存在时才进行写入。现在很酷的事情是:使用标准调用使用fdopen读/写此文件。
fdopen
和open
还是fopen
和open
? - user7116fopen
是标准C库的一部分,而open
则不是。编写可移植代码时应使用fopen
。 - Aziz