Stream Routines

Stream I/O functions handle data as a continuous stream of characters. To use the stream functions, you must include the file STDIO.H in your program. This file defines constants, types, and structures used in the stream functions, and contains function declarations and macro definitions for the stream routines.

When a file is opened for I/O using the stream functions, the opened file is associated with a structure of type FILE (defined in STDIO.H) containing basic information about the file. A pointer to the FILE structure is returned when the stream is opened. Subsequent operations use this pointer (also called the “stream pointer,” or just “stream”) to refer to the file.

The stream functions provide for buffered, formatted, or unformatted input and output. When a stream is buffered, data that is read from or written to the stream is collected in an intermediate storage location called a “buffer.” In write operations, the output buffer's contents are written to the appropriate final location when the buffer is full, the stream is closed, or the program terminates normally. The buffer is said to be “flushed” when this occurs. In read operations, a block of data is placed in the input buffer. When the input buffer is empty, the next block of data is transferred into the buffer.

Buffering produces efficient I/O because the system can transfer a large block of data in a single operation rather than performing an I/O operation each time a data item is read from or written to a stream. However, if a program terminates abnormally, output buffers may not be flushed, resulting in loss of data.

You can use the fflush and _flushall routines to ensure that the buffer associated with the specified file or all of the open buffers are flushed to the operating system. If a file was opened with fopen or _fdopen and the c flag, or if the program is linked with COMMODE.OBJ, the contents of a flushed buffer are written to disk.

Some of the constants defined in STDIO.H may be useful in your program. The manifest constant EOF is defined to be the value returned at end-of-file. NULL is the null pointer. FILE is the structure that maintains information about a stream. BUFSIZ defines the default size of stream buffers, in bytes.

Routine Use

clearerr Clears the error indicator for a stream
fclose Closes a stream
_fcloseall Closes all open streams
_fdopen Associates a stream with an open file handle
feof Tests for end-of-file on a stream
ferror Tests for error on a stream
fflush Flushes a stream
fgetc Reads a character from a stream (function version)
_fgetchar Reads a character from stdin (function version)
fgetpos Gets the position indicator of a stream
fgets Reads a string from a stream
_fileno Gets the file handle associated with a stream
_flushall Flushes all streams
fopen Opens a stream
fprintf Writes formatted data to a stream
fputc Writes a character to a stream (function version)
_fputchar Writes a character to stdout (function version)
fputs Writes a string to a stream
fread Reads unformatted data from a stream
freopen Reassigns a FILE pointer to a new file
fscanf Reads formatted data from a stream
fseek Moves file position to a given location
fsetpos Sets the position indicator of a stream
_fsopen Opens a stream with file sharing
ftell Gets current file position
fwrite Writes unformatted data items to a stream
getc Reads a character from a stream
getchar Reads a character from stdin
gets Reads a line from stdin
_getw Reads a binary int item from a stream
printf Writes formatted data to stdout
putc Writes a character to a stream
putchar Writes a character to stdout
puts Writes a line to a stream
_putw Writes a binary int item to a stream
rewind Moves file position to beginning of a stream
_rmtmp Removes temporary files created by tmpfile
scanf Reads formatted data from stdin
setbuf Controls stream buffering
setvbuf Controls stream buffering and buffer size
_snprintf Writes formatted data of a specified length to a string
sprintf Writes formatted data to a string
sscanf Reads formatted data from a string
_tempnam Generates a temporary filename in given directory
tmpfile Creates a temporary file
tmpnam Generates a temporary filename
ungetc Places a character in the buffer
vfprintf Writes formatted data to a stream
vprintf Writes formatted data to stdout
_vsnprintf Writes formatted data of a specified length to a string
vsprintf Writes formatted data to a string

Opening a Stream

A stream must be opened using the _fdopen, fopen, freopen, or _fsopen function before input and output can be performed on that stream. When opening a stream, the named stream can be opened for reading, writing, or both, and it can be opened in either text or binary mode.

The _fdopen, fopen, freopen, and _fsopen functions return a FILE pointer. You normally assign the pointer value to a variable and use the variable to refer to the opened stream. For instance, if your program contains the lines

FILE *infile

infile = fopen ("test.dat", “r”);

you can use the FILE pointer variable infile to refer to the stream.

Using Predefined Stream Pointers

When a program begins execution, the startup code automatically opens several streams: standard input, standard output, and standard error. By default, the standard input, standard output, and standard error streams are directed to the console (keyboard and screen). This means that when a program expects input from the “standard input,” it receives that input from the console. Similarly, a program that writes to the “standard output” prints its data to the console. Error messages generated by the library routines are sent to the “standard error,” meaning that error messages appear on the user's console.

With DOS, two additional streams are opened: standard auxiliary and standard print. The assignment of standard auxiliary and standard print depends on the machine configuration. These streams usually refer to the first serial port and a printer port, but those ports may not be available on some systems. Be sure to check your machine configuration before using these streams.

You can refer to the standard streams with the following predefined stream pointers:

Pointer Stream

stdin Standard input
stdout Standard output
stderr Standard error
stdaux Standard auxiliary (DOS only)
stdprn Standard print (DOS only)

You can use these pointers in any function that requires a stream pointer as an argument. Some functions, such as getchar and putchar, are designed to use stdin or stdout automatically. The pointers stdin, stdout, stderr, stdaux, and stdprn are constants, not variables; do not try to assign them a new stream pointer value.

DOS allows you to redirect a program's standard input and standard output at the operating-system command level. See your operating-system user's manual for a complete discussion of redirection.

Within your program, you can use freopen to redirect stdin, stdout, stderr, stdaux, or stdprn so that it refers to a disk file or to a device. See the reference description of freopen for more details.

Controlling Stream Buffering

As mentioned earlier, stream routines can use in-memory buffers to speed I/O operations. Files opened using the stream routines are buffered by default, except for stdaux and stdprn, which are normally unbuffered. The stdout and stderr streams are flushed whenever they are full or (if you are writing to a character device) after each library call.

By using the setbuf or setvbuf function, you can cause a stream to be unbuffered, or you can associate a buffer with an unbuffered stream. Buffers allocated by the system are not accessible to you, but buffers allocated with setbuf or setvbuf refer to arrays in your program and can be manipulated. Buffers can be any size up to INT_MAX bytes. This size is set by the manifest constant BUFSIZ in STDIO.H if you use seftbuf; if you use setvbuf, you can set the size of the buffer yourself. (See the descriptions of setbuf and setvbuf in the reference section for more details.)

Note:

These routines affect only buffers created by the run-time library routines. They have no effect on buffers created by the operating system.

Committing Buffer Contents to Disk

Normally, both the fflush and the _flushall functions pass the contents of a program buffer to the operating system, which can cache data before writing it to disk. In the case of a system failure, data cached by the operating system will be lost. The commit-to-disk feature ensures that the flushed contents of a buffer are written to storage media.

There are two ways to commit buffer contents to disk:

Link with the file COMMODE.OBJ (provided with Microsoft C/C++) to set a global commit flag. The default setting of the global flag is “no-commit.”

Set the c “commit” flag with fopen or _fdopen to open the file in commit mode. The n flag specifies the “no-commit” mode.

COMMODE.OBJ allows existing code to use the commit feature. Any file specifically opened with either the c or the n flag will behave according to the flag, regardless of the state of the global commit/no-commit flag. Thus, some files can be opened with committing contents to disk and some without.

Closing Streams

The fclose and _fcloseall functions close a stream or streams. The fclose routine closes a single specified stream; _fcloseall closes all open streams except stdin, stdout, stderr, stdaux, and stdprn. If your program does not explicitly close a stream, the stream is automatically closed when the program terminates. How-ever, it is a good practice to close a stream when your program is finished with it, as the number of streams that can be open at a given time is limited.

Reading and Writing Data

The stream functions allow you to transfer data in a variety of ways. You can read and write binary data (a sequence of bytes), or specify reading and writing by characters, lines, or more complicated formats.

Reading and writing operations on streams always begin at the current position of the stream, known as the “file pointer” for the stream. The file pointer is changed to reflect the new position after a read or write operation takes place. For example, if you read a single character from a stream, the file pointer is increased by one byte so that the next operation begins with the first unread character. If a stream is opened for appending, the file pointer is automatically positioned at the end of the file before each write operation.

When switching directly between output and input, there must be an intervening call to the fflush function or to a file-positioning function (fseek, fsetpos, or rewind). Input can be directly followed by output without an intervening call to a file-positioning function if the input operation encounters end-of-file.

The fseek and fsetpos functions allow you to position the file pointer anywhere in a file. The next operation occurs at the position you specified. The rewind routine positions the file pointer at the beginning of the file. Use the ftell or fgetpos routine to determine the current position of the file pointer.

The feof macro detects an end-of-file condition on a stream. Once the end-of-file indicator is set, it remains set until the file is closed, or until clearerr, fseek, fsetpos, or rewind is called.

Streams associated with a character-oriented device (such as a console) do not have file pointers. Data coming from or going to a console cannot be accessed randomly. Routines that set or get the file-pointer position (such as fseek, fgetpos, fsetpos, ftell, or rewind) have undefined results if used on a stream associated with a character-oriented device.

Detecting Errors

When an error occurs in a stream operation, an error indicator for the stream is set. You can use the ferror macro to test the error indicator and determine whether an error has occurred. Once an error has occurred, the error indicator for the stream remains set until the stream is closed, or until you explicitly clear the error indicator by calling clearerr or rewind.