文件描述符和文件指针之间有什么区别?


Answers:


144

文件描述符是一个低级整数“句柄”,用于在Linux和其他类似Unix的系统中在内核级别标识打开的文件(或套接字,或其他)。

您将“裸”文件描述符传递给实际的Unix调用,例如read()write()等等。

FILE指针是一个C标准库级构建体,用于表示一个文件。该FILE包装的文件描述符,并增加了缓冲等功能,使I / O更容易。

您将FILE指针传递给标准C函数,例如fread()fwrite()


@nvl:fildes肯定可用于Windows,例如msdn.microsoft.com/en-us/library/z0kc8e3z%28VS.80%29.aspx
kennytm 2010年

2
@unwind“裸”文件描述符是什么意思?链接的参考资料说,fd是的第一个参数read()。你为什么称它为裸体?
极客

3
@Geek与标准库的FILE *类型相比,整数文件描述符是“较少包装”的,即“裸”的。
2014年

57

一个是缓冲(FILE *),另一个不是。实际上,FILE *除非您知道自己在做什么,或者除非文件实际上是一个套接字,否则您几乎总是在从“真实”文件(即在驱动器上)中读取文件时使用。

您可以从FILE *using 获取文件描述符,fileno()并且可以FILE *使用using从文件描述符中打开缓冲区fdopen()


12
+1指出fileno(),手册页的组织使其很难找到。与fdopen()相同。
里文希尔

20

文件描述符只是您从POSIX open()调用中获得的整数。使用标准C fopen()可以FILE返回结构。该FILE结构除其他外还包含此文件描述符,例如文件结束和错误指示符,流位置等。

因此fopen(),与相比,使用给您提供了一定数量的抽象open()。通常,您应该使用它,fopen()因为它具有更高的可移植性,并且您可以使用使用该FILE结构(即fprintf()和系列)的所有其他标准C函数。

使用任何一个都没有性能问题。


8
+1带来便携性。FILE是标准C库的一部分(返回C89 / C90);文件描述符不是。
tomlogic

15

文件描述符与文件指针

文件描述符:

文件描述符是open()系统调用返回的整数值。

int fd = open (filePath, mode);

  1. 低/内核级别的处理程序。
  2. 传递给UNIX系统调用的read()和write()。
  3. 不包括缓冲和此类功能。
  4. 便携式性较差,效率不足。

文件指针:

文件指针是指向fopen()库函数返回的C结构的指针,该函数用于标识文件,包装文件描述符,缓冲功能以及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;
  1. 这是高级界面。
  2. 传递给fread()和fwrite()函数。
  3. 包括缓冲,错误指示和EOF检测等。
  4. 提供更高的可移植性和效率。

1
您是否可以支持更高效率的主张?我从未听说过。
Gid

1
“效率”主张可能是由于缓冲。使用文件描述符,每个read()或write()都是一个系统调用,并且每个系统调用都应被认为是昂贵的。使用FILE *,缓冲意味着某些读写不会成为系统调用。
麦克·斯皮尔'18

12

要添加可能有用的点。

关于 FILE *

  1. 不能用于进程间通信(IPC)。
  2. 当您需要通用缓冲I / O时使用它(printf,frpintf,snprintf,scanf)
  3. 我将它多次用于调试日志。例,

                 FILE *fp;
                 fp = fopen("debug.txt","a");
                 fprintf(fp,"I have reached till this point");
                 fclose(fp);
    

关于 FILE DESCRIPTOR

  1. 通常用于IPC。

  2. 对* nix系统上的文件(设备,文件,套接字等)进行低级控制,因此比.x更强大FILE *


您不能使用fdopen()IPC和设备做诸如此类的事情FILE*吗?
osvein

实际上,是和不是。您无法使用来设置和初始化IPC FILE*,但可以FILE*从文件描述符(fdopen())创建一个,然后关闭FILE也会关闭该描述符。因此,您可以执行 IPC,但是您必须稍微处理文件描述符以促进任何直接IPC。
米卡W

3

FILE *更有用,当你用文本文件和用户输入/输出工作,因为它允许你使用API功能,如sprintf()sscanf()fgets()feof()等。

文件描述符API是低级的,因此它允许使用套接字,管道,内存映射文件(当然还有常规文件)。


1
+1是因为您添加了内存映射文件,从我目前的阅读开始,已经提供了其他答案。
ernie.cordell 2014年

3

只要注意一下,即可结束讨论(如果有兴趣的话)...

fopen可能是不安全的,您可能应该使用fopen_sopen设置了独占位。C1X是提供x模式,这样你就可以fopen与模式"rx""wx"等等。

如果使用open,则可以考虑open(..., O_EXCL | O_RDONLY,... )open(..., O_CREAT | O_EXCL | O_WRONLY,... )

例如,请参见不要假设fopen()和文件创建


由于fopen_s似乎没有办法POSIX,我认为最轻便的灵魂就是到open(2)那时fdopen(2)。(将窗户放在一边)。此外,会更快fopen_s()或更open(2)紧随其后的是fdopen(2)什么?
Mihir

1

系统调用主要使用文件描述符,例如readwrite。库函数将使用文件指针(printfscanf)。但是,库函数仅在内部使用系统调用。


我不确定为什么要说库函数仅使用内部系统调用:如果您指的是标准CI / O(或其他与此相关的函数)函数,那么我不确定(普遍吗?)是真的。否则,这不是您所说的,因此,我希望您的帖子中的语言有所整理。最后一句话让我感到困惑。
ernie.cordell 2014年

1

我在这里找到了很好的资源,对两者之间的差异进行了高层次的概述:

当您要输入或输出到文件时,可以选择两种基本机制来表示程序与文件之间的连接:文件描述符和流。文件描述符表示为int类型的对象,而流表示为FILE *对象。

文件描述符为输入和输出操作提供了原始的低级接口。文件描述符和流都可以表示与设备(例如终端)的连接,或者用于与另一个进程进行通信的管道或套接字以及普通文件的连接。但是,如果要执行特定于特定类型设备的控制操作,则必须使用文件描述符;没有以这种方式使用流的设施。如果程序需要在特殊模式下(例如非阻塞(或轮询)输入)进行输入或输出,则还必须使用文件描述符(请参见文件状态标志)。

流提供了一个更高层的接口,位于原始文件描述符工具之上。流接口对所有类型的文件都非常相似-唯一的例外是可以选择的三种缓冲样式(请参见流缓冲)。

使用流接口的主要优点是,与用于文件描述符的相应功能相比,用于在流上执行实际输入和输出操作(与控制操作相对)的功能集要丰富得多,功能也要强大得多。文件描述符接口仅提供用于传输字符块的简单功能,而流接口还提供了功能强大的格式化输入和输出功能(printf和scanf)以及面向字符和行的输入和输出功能。

由于流是根据文件描述符实现的,因此您可以从流中提取文件描述符,然后直接对文件描述符执行低级操作。您还可以首先打开一个连接作为文件描述符,然后创建与该文件描述符关联的流。

通常,除非要执行某些只能在文件描述符上执行的特定操作,否则应坚持使用流而不是文件描述符。如果您是新手程序员,并且不确定要使用哪些函数,建议您专注于格式化输入函数(请参阅格式化输入)和格式化输出函数(请参见格式化输出)。

如果您担心程序到GNU以外的系统的可移植性,则还应该注意文件描述符不像流那样可移植。您可以期望任何运行ISO C的系统都支持流,但是非GNU系统可能根本不支持文件描述符,或者只能实现对文件描述符进行操作的GNU函数的子集。但是,GNU C库中的大多数文件描述符函数都包含在POSIX.1标准中。

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.