我想知道文件描述符和文件指针之间的区别。
另外,在什么情况下您会使用其中一种而不是另一种?
一个是缓冲的 ( FILE *
),另一个不是。在实践中,您FILE *
几乎总是希望在从“真实”文件(即驱动器上)读取时使用,除非您知道自己在做什么或者除非您的文件实际上是一个套接字左右。
FILE *
您可以从using获取文件描述符,您可以使用从文件描述符fileno()
打开缓冲FILE *
fdopen()
文件描述符只是您从 POSIXopen()
调用中获得的整数。使用标准 C fopen()
,你会得到一个FILE
结构体。该FILE
结构包含此文件描述符以及其他内容,例如文件结束和错误指示符、流位置等。
因此 usingfopen()
与open()
. 一般来说,您应该使用fopen()
它,因为它更具可移植性,并且您可以使用所有其他使用FILE
struct iefprintf()
和 family 的标准 C 函数。
使用两者都没有性能问题。
文件描述符与文件指针
文件描述符:
文件描述符是open()
系统调用返回的整数值。
int fd = open (filePath, mode);
文件指针:
File Pointer 是指向库函数返回的 C 结构的指针,fopen()
用于标识文件、包装文件描述符、缓冲功能以及 I/O 操作所需的所有其他功能。文件指针是FILE类型,其定义可以在"/usr/include/stdio.h"中找到。这个定义可能因一个编译器而异。
FILE *fp = fopen (filePath, mode);
// A FILE Structure returned by fopen
typedef struct
{
unsigned char *_ptr;
int _cnt;
unsigned char *_base;
unsigned char *_bufendp;
short _flag;
short _file;
int __stdioid;
char *__newbase;
#ifdef _THREAD_SAFE
void *_lock;
#else
long _unused[1];
#endif
#ifdef __64BIT__
long _unused1[4];
#endif /* __64BIT__ */
} FILE;
想要添加可能有用的点。
关于FILE *
我多次将它用于调试日志。例子,
FILE *fp;
fp = fopen("debug.txt","a");
fprintf(fp,"I have reached till this point");
fclose(fp);
关于FILE DESCRIPTOR
一般用于IPC。
对 *nix 系统上的文件进行低级控制。(设备、文件、套接字等),因此比FILE *
.
FILE *
在处理文本文件和用户输入/输出时更有用,因为它允许您使用 API 函数,如、sprintf()
、sscanf()
等。fgets()
feof()
文件描述符 API 是低级的,因此它允许使用套接字、管道、内存映射文件(当然还有常规文件)。
只需一个便条即可完成讨论(如果有兴趣)....
fopen
可能不安全,您可能应该使用fopen_s
oropen
设置独占位。C1X 提供x
模式,所以你可以fopen
使用模式"rx"
,"wx"
等等。
如果你使用open
,你可能会考虑open(..., O_EXCL | O_RDONLY,... )
或open(..., O_CREAT | O_EXCL | O_WRONLY,... )
。
例如,请参阅不要对 fopen() 和文件创建做出假设。
我在这里找到了一个很好的资源,对两者之间的差异进行了高级概述:
当您想要对文件进行输入或输出时,您可以选择两种基本机制来表示程序和文件之间的连接:文件描述符和流。文件描述符表示为 int 类型的对象,而流表示为 FILE * 对象。
文件描述符为输入和输出操作提供了一个原始的低级接口。文件描述符和流都可以表示与设备(例如终端)的连接,或用于与另一个进程通信的管道或套接字,以及普通文件。但是,如果您想要执行特定于特定类型设备的控制操作,则必须使用文件描述符;没有以这种方式使用流的设施。如果您的程序需要在特殊模式下进行输入或输出,例如非阻塞(或轮询)输入(请参阅文件状态标志),您还必须使用文件描述符。
流提供了一个更高级别的接口,位于原始文件描述符设施之上。流接口处理所有类型的文件非常相似——唯一的例外是您可以选择的三种缓冲样式(请参阅流缓冲)。
使用流接口的主要优点是,用于对流执行实际输入和输出操作(与控制操作相反)的一组函数比文件描述符的相应工具更丰富、更强大。文件描述符接口只提供了传输字符块的简单函数,但流接口还提供了强大的格式化输入和输出函数(printf 和 scanf)以及面向字符和行的输入和输出函数。
由于流是根据文件描述符实现的,因此您可以从流中提取文件描述符并直接对文件描述符执行低级操作。您还可以最初将连接作为文件描述符打开,然后创建与该文件描述符关联的流。
一般来说,你应该坚持使用流而不是文件描述符,除非你想做一些只能在文件描述符上完成的特定操作。如果您是初学者并且不确定要使用哪些函数,我们建议您专注于格式化输入函数(请参阅格式化输入)和格式化输出函数(请参阅格式化输出)。
If you are concerned about portability of your programs to systems other than GNU, you should also be aware that file descriptors are not as portable as streams. You can expect any system running ISO C to support streams, but non-GNU systems may not support file descriptors at all, or may only implement a subset of the GNU functions that operate on file descriptors. Most of the file descriptor functions in the GNU C Library are included in the POSIX.1 standard, however.
系统调用大多使用文件描述符,例如read
和 write
. 库函数将使用文件指针 ( printf
, scanf
)。但是,库函数仅使用内部系统调用。