C语言 文件描述符和文件指针有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2423628/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:49:09  来源:igfitidea点击:

What's the difference between a file descriptor and file pointer?

cfile-descriptorfile-pointer

提问by karthi_ms

I want to know the difference between a file descriptor and file pointer.

我想知道文件描述符和文件指针之间的区别。

Also, in what scenario would you use one instead of the other?

另外,在什么情况下您会使用一种而不是另一种?

回答by unwind

A file descriptor is a low-level integer "handle" used to identify an opened file (or socket, or whatever) at the kernel level, in Linux and other Unix-like systems.

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

You pass "naked" file descriptors to actual Unix calls, such as read(), write()and so on.

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

A FILEpointer is a C standard library-level construct, used to represent a file. The FILEwraps the file descriptor, and adds buffering and other features to make I/O easier.

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

You pass FILEpointers to standard C functions such as fread()and fwrite().

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

回答by Ben

One is buffered (FILE *) and the other is not. In practice, you want to use FILE *almost always when you are reading from a 'real' file (ie. on the drive), unless you know what you are doing or unless your file is actually a socket or so..

一个被缓冲 ( FILE *) 而另一个没有。实际上,FILE *当您从“真实”文件(即在驱动器上)读取时,您几乎总是希望使用它,除非您知道自己在做什么,或者除非您的文件实际上是一个套接字等。

You can get the file descriptor from the FILE *using fileno()and you can open a buffered FILE *from a file descriptor using fdopen()

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

回答by Martin Wickman

A file descriptor is just an integer which you get from the POSIX open()call. Using the standard C fopen()you get a FILEstruct back. The FILEstruct contains this file descriptor amongst other things such as end-of-file and error indicator, stream position etc.

文件描述符只是您从 POSIXopen()调用中获得的整数。使用标准 C,fopen()你会得到一个FILE结构体。该FILE结构包含此文件描述符以及其他内容,例如文件结束和错误指示符、流位置等。

So using fopen()gives you a certain amount of abstraction compared to open(). In general you should be using fopen()since that is more portable and you can use all the other standard C functions that uses the FILEstruct, i.e., fprintf()and family.

因此fopen(),与open(). 一般来说,您应该使用它,fopen()因为它更易于移植,并且您可以使用所有其他使用FILE结构体的标准 C 函数,即,fprintf()和系列。

There are no performance issues using either.

使用两者都没有性能问题。

回答by Yogeesh H T

File descriptor vs File pointer

文件描述符与文件指针

File descriptor:

文件描述符:

File Descriptor is an integer value returned by open()system call.

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

int fd = open (filePath, mode);

int fd = open (filePath, mode);

  1. Low/Kernel level handler.
  2. passe to read() and write() of UNIX System Calls.
  3. Doesn't include buffering and such features.
  4. Less portable and lacks efficiency.
  1. 低/内核级处理程序。
  2. 传递给 UNIX 系统调用的 read() 和 write()。
  3. 不包括缓冲等功能。
  4. 便携性差,效率低。

File pointer:

文件指针:

File Pointer is a pointer to a C structure returned by fopen()library function, which is used to identifying a file, wrapping the file descriptor, buffering functionality and all other functionality needed for I/O operation.The file pointer is of type FILE, whose definition can be found in "/usr/include/stdio.h". This definition may vary from one compiler to another.

文件指针是指向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. It is high level interface.
  2. Passed to fread() and fwrite() functions.
  3. Includes buffering,error indication and EOF detection,etc.
  4. Provides higher portability and efficiency.
  1. 它是高级接口。
  2. 传递给 fread() 和 fwrite() 函数。
  3. 包括缓冲、错误指示和EOF检测等。
  4. 提供更高的便携性和效率。

回答by Akshay Patil

Want to add points which might be useful.

想添加可能有用的点。

ABOUT FILE *

关于 FILE *

  1. can't be used for interprocess communication(IPC).
  2. use it when you need genral purpose buffered I/O.(printf,frpintf,snprintf,scanf)
  3. I use it many times for debug logs. example,

                 FILE *fp;
                 fp = fopen("debug.txt","a");
                 fprintf(fp,"I have reached till this point");
                 fclose(fp);
    
  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);
    

ABOUT FILE DESCRIPTOR

关于 FILE DESCRIPTOR

  1. It's generally used for IPC.

  2. Gives low-level control to files on *nix systems.(devices,files,sockets,etc), hence more powerfull than the FILE *.

  1. 一般用于IPC。

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

回答by jww

Just a note to finish out the discussion (if interested)....

只是完成讨论的注释(如果有兴趣)......

fopencan be insecure, and you should probably use fopen_sor openwith exclusive bits set. C1X is offering xmodes, so you can fopenwith modes "rx", "wx", etc.

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

If you use open, you might consider open(..., O_EXCL | O_RDONLY,... )or open(..., O_CREAT | O_EXCL | O_WRONLY,... ).

如果您使用open,您可能会考虑open(..., O_EXCL | O_RDONLY,... )open(..., O_CREAT | O_EXCL | O_WRONLY,... )

See, for example, Do not make assumptions about fopen() and file creation.

例如,请参阅不要对 fopen() 和文件创建进行假设

回答by qrdl

FILE *is more useful when you work with text files and user input/output, because it allows you to use API functions like sprintf(), sscanf(), fgets(), feof()etc.

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

File descriptor API is low-level, so it allows to work with sockets, pipes, memory-mapped files (and regular files, of course).

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

回答by Pavunkumar

System calls are mostly using file descriptor, for example readand write. Library function will use the file pointers ( printf, scanf). But, library functions are using internally system calls only.

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

回答by Suraj Jain

I found a good resource here, giving high level overview of differences between the two:

我在这里找到了一个很好的资源,提供了两者之间差异的高级概述:

When you want to do input or output to a file, you have a choice of two basic mechanisms for representing the connection between your program and the file: file descriptors and streams. File descriptors are represented as objects of type int, while streams are represented as FILE * objects.

File descriptors provide a primitive, low-level interface to input and output operations. Both file descriptors and streams can represent a connection to a device (such as a terminal), or a pipe or socket for communicating with another process, as well as a normal file. But, if you want to do control operations that are specific to a particular kind of device, you must use a file descriptor; there are no facilities to use streams in this way. You must also use file descriptors if your program needs to do input or output in special modes, such as nonblocking (or polled) input (see File Status Flags).

Streams provide a higher-level interface, layered on top of the primitive file descriptor facilities. The stream interface treats all kinds of files pretty much alike—the sole exception being the three styles of buffering that you can choose (see Stream Buffering).

The main advantage of using the stream interface is that the set of functions for performing actual input and output operations (as opposed to control operations) on streams is much richer and more powerful than the corresponding facilities for file descriptors. The file descriptor interface provides only simple functions for transferring blocks of characters, but the stream interface also provides powerful formatted input and output functions (printf and scanf) as well as functions for character- and line-oriented input and output.

Since streams are implemented in terms of file descriptors, you can extract the file descriptor from a stream and perform low-level operations directly on the file descriptor. You can also initially open a connection as a file descriptor and then make a stream associated with that file descriptor.

In general, you should stick with using streams rather than file descriptors, unless there is some specific operation you want to do that can only be done on a file descriptor. If you are a beginning programmer and aren't sure what functions to use, we suggest that you concentrate on the formatted input functions (see Formatted Input) and formatted output functions (see Formatted Output).

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.

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

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

流提供了一个更高级别的接口,位于原始文件描述符设施之上。流接口对待所有类型的文件都非常相似——唯一的例外是您可以选择的三种缓冲方式(请参阅流缓冲)。

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

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

一般来说,你应该坚持使用流而不是文件描述符,除非你想要做一些只能在文件描述符上完成的特定操作。如果您是初学者并且不确定要使用哪些函数,我们建议您专注于格式化输入函数(参见格式化输入)和格式化输出函数(参见格式化输出)。

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