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 library are included in the POSIX.1 standard, however.
There are many functions for performing low-level input/output operations on file descriptors. These functions are described in Low-Level I/O. They include functions for performing low-level control operations for which there are no equivalents on streams.
Stream-level I/O is more flexible and usually more convenient; therefore, programmers generally use the descriptor-level functions only when necessary. These are some of the usual reasons:
fileno
to get the descriptor
corresponding to a stream.)
For historical reasons, the type of the C data structure that represents
a stream is called FILE
rather than “stream”. Since most of
the library functions deal with objects of type FILE *
, sometimes
the term file pointer is also used to mean “stream”. This leads
to unfortunate confusion over terminology in many books on C. This
manual, however, is careful to use the terms “file” and “stream”
only in the technical sense.
The FILE
type is declared in the header file stdio.h.
This is the data type used to represent stream objects. A
FILE
object holds all of the internal state information about the connection to the associated file, including such things as the file position indicator and buffering information. Each stream also has error and end-of-file status indicators that can be tested with theferror
andfeof
functions; see EOF and Errors.
FILE
objects are allocated and managed internally by the
input/output library functions. Don't try to create your own objects of
type FILE
; let the library do it. Your programs should
deal only with pointers to these objects (that is, FILE *
values)
rather than the objects themselves.
The following table compares some of the aspects and functions of low-level and stream input/output.
Feature | Low-Level | Stream |
---|---|---|
File ID | int | FILE *
|
buffering | no | yes |
open/close | open ,
close | fopen , fclose
|
block read/write | read ,
write | fread , fwrite
|
set file position | lseek | fseek
|
flush buffers | N/A | fflush
|
device control | ioctl | N/A |
file information | fstat | N/A |
Each file stream is associated with a low-level file descriptor. You can mix low-level input and output operations with high-level stream operations, but this is generally unwise, as the effects of buffering can be difficult to detect.
#include <stdio.h> int fileno(FILE *stream); FILE *fdopen(int filedes, const char *mode); |
The fileno
function returns the file descriptor for a
given stream, or -1 on failure. This function can be useful if you
need low-level access to an open stream, for example, to call
fstat
on it.
We can create a new file stream based on an already-opened file
descriptor by calling the fdopen
function. Essentially,
this function provides stream buffers around an already-open file.
The mode
parameter string is the same as that used by
fopen
and must be compatible with those established for
the already-open file.
Streams and File Descriptors (from the GNU C Library Reference Manual).
Input/Output Overview (from the GNU C Library Reference Manual).
Neil Matthew and Richard Stone, Beginning Linux Programming,
Third Edition,
Wrox, 2004. ISBN 0-7645-4497-7. p 91-134.
W. Richard Stevens and Stephen A. Rago, Advanced Programming in the UNIX Environment, Second Edition, Addison Wesley, 2005. ISBN 0-201-43307-9.
Maintained by John Loomis, last updated 4 September 2006