Overview of I/O Streams

The I/O Stream Classes provide the standard input and output capabilities for C++. In C++, input and output are described in terms of streams. The processing of these streams is done at two levels. The first level treats the data as sequences of characters; the second level treats it as a series of values of a particular type.

There are two primary base classes for the I/O Stream Classes:

  1. The streambuf class and the classes derived from it (strstreambuf, stdiobuf, and filebuf) implement the stream buffers. Stream buffers act as temporary repositories for characters that are coming from the ultimate producers of input or are being sent to the ultimate consumers of output.
  2. The ios class maintains formatting and error-state information for these streams. The classes derived from ios implement the formatting of these streams. This formatting involves converting sequences of characters from the stream buffer into values of a particular type and converting values of a particular type into their external display format.

The I/O Stream Classes predefine streams for standard input, standard output, and standard error. If you want to open your own streams for input or output, you must create an object of an appropriate I/O Streams class. The iostream constructor takes as an argument a pointer to a streambuf object. This object is associated with the device, file, or array of bytes in memory that is going to be the ultimate producer of input or the ultimate consumer of output.

Input and Output for User-Defined Classes

You can overload the input and output operators for the classes that you create yourself. Once you have overloaded the input and output operators for a class, you can perform input and output operations on objects of that class in the same way that you would perform input and output on char, int, double, and the other built-in types.

The I/O Stream Class Hierarchy

The I/O Stream Classes have two base classes, streambuf and ios.

The streambuf class implements stream buffers. streambuf is the base class for the following classes:

The ios class maintains formatting and error state information for streams. Streams are implemented as objects of the following classes that are derived from ios:

The classes that are derived from ios are themselves base classes.

istream is the input stream class. It implements stream buffer input, or input operations. The following classes are derived from istream:

ostream is the output stream class. It implements stream buffer output, or output operations. The following classes are derived from ostream:

iostream is the class that combines istream and ostream to implement input and output to stream buffers. The following classes are derived from iostream:

Note: The I/O Stream Classes also define other classes, including fstreambase and strstreambase. These classes are meant for the internal use of the I/O Stream Classes. Do not use them directly.

I/O Stream Header Files

To use an I/O Stream class, you must include the appropriate header files for that class. The following lists the I/O Stream header files and the classes that they cover:

iostream.h contains declarations for the basic classes:

fstream.h contains declarations for the classes that deal with files:

stdiostream.h contains declarations for stdiobuf and stdiostream, the classes that specialize streambuf and ios, respectively, to use the FILE structures defined in the C header file stdio.h. Note: the 8.3 file naming convention compliant name of this file on OS/2 is stdiostr.h.

strstream.h contains declarations for the classes that deal with character strings. Note: the 8.3 file naming convention compliant name of this file on OS/2 is strstrea.h. The first "str" in each of these names stands for "string":

iomanip.h contains declarations for the parameterized manipulators. Manipulators are values that you can insert into streams or extract from streams to affect or query the behavior of the streams.

stream.h is used for compatibility with earlier versions of the I/O Stream Classes. It includes iostream.h, fstream.h, stdiostream.h, and iomanip.h, along with some definitions needed for compatibility with the AT&T C++ Language System Release 1.2. Only use this header file with existing code; do not use it with new C++ code.

Note: If you use the obsolete function form() declared in stream.h, there is a limit to the size of the format specifier. If you call form() with a format specifier string longer than this limit, a runtime message will be generated and the program will terminate.

Stream Buffers

One of the most important concepts in the I/O Stream Classes is the stream buffer. The streambuf class implements some of the member functions that define stream buffers, but other specialized member functions are left to the classes that are derived from streambuf: strstreambuf, stdiobuf, and filebuf.

Note: The AT&T and UNIX System Laboratories C++ Language System documentation use the terms reserve area and buffer instead of stream buffer.

What Does a Stream Buffer Do?

A stream buffer acts as a buffer between the ultimate producer (the source of data) or ultimate consumer (the target of data) and the member functions of the classes derived from ios that format this raw data. The ultimate producer can be a file, a device, or an array of bytes in memory. The ultimate consumer can also be a file, a device, or an array of bytes in memory.

Why Use a Stream Buffer?

In most operating systems, a system call to read data from the ultimate producer or write it to the ultimate consumer is an expensive operation. If your applications can reduce the number of system calls they have to make, they will usually be more efficient. By acting as a buffer between the ultimate producer or ultimate consumer and the formatting functions, a stream buffer can reduce the number of system calls that are made.

Consider, for example, an application that is reading data from the ultimate producer. If there is no buffer, the application has to make a system call for each character that is read. However, if the application uses a stream buffer, system calls will only be made when the buffer is empty. Each system call will read enough characters from the ultimate producer (if they are available) to fill the buffer again.

Format State Flags

The ios class defines an enumeration of format state flags that you can use to affect the formatting of data in I/O streams. The following list shows the formatting features and the format flags that control them:

Using Manipulators

Manipulators provide a convenient way of changing the characteristics of an input or output stream, using the same syntax that is used to insert or extract values. With manipulators, you can embed a function call in an expression that contains a series of insertions or extractions. Manipulators usually provide shortcuts for sequences of iostream library operations.

The iomanip.h header file contains a definition for a macro IOMANIPdeclare(). IOMANIPdeclare() takes a type name as an argument and creates a series of classes you can use to define manipulators for a given kind of stream. Calling the macro IOMANIPdeclare() with a type as an argument creates a series of classes that let you define manipulators for your own classes. If you call IOMANIPdeclare() with the same argument more than once in a file, you will get a syntax error.

Simple Manipulators and Parameterized Manipulators

There are two kinds of manipulators:

Simple manipulators do not take any arguments. The following classes have built-in simple manipulators:

Parameterized manipulators require one or more arguments. setfill (near the bottom of the iomanip.h header file) is an example of a parameterized manipulator. You can create your own parameterized manipulators and your own simple manipulators.

ios Methods and Manipulators

For some of the format flags defined for the ios class, you can set or clear them using an ios function and a flag name, or by using a manipulator. With manipulators you can place the change to a stream's state within a list of outputs for that stream.