3. Using the C++ Compiler Options
6. Creating and Using Templates
9. Improving Program Performance
10. Building Multithreaded Programs
12. Using The C++ Standard Library
13. Using the Classic iostream Library
13.2 Basic Structure of iostream Interaction
13.3 Using the Classic iostream Library
13.3.1.1 Defining Your Own Insertion Operator
13.3.1.2 Handling Output Errors
13.3.3 Defining Your Own Extraction Operators
13.3.4 Using the char* Extractor
13.3.5 Reading Any Single Character
13.3.10 Using iostreams With stdio
13.4.1 Dealing With Files Using Class fstream
13.4.1.2 Declaring an fstream Without Specifying a File
13.4.1.3 Opening and Closing Files
13.4.1.4 Opening a File Using a File Descriptor
13.4.1.5 Repositioning Within a File
13.7.1 Using Plain Manipulators
13.7.2 Parameterized Manipulators
13.8 Strstreams: iostreams for Arrays
13.9 Stdiobufs: iostreams for stdio Files
iostreams are the formatting part of a two-part (input or output) system. The other part of the system is made up of streambufs, which deal in input or output of unformatted streams of characters.
You usually use streambufs through iostreams, so you don’t have to worry about the details of streambufs. You can use streambufs directly if you choose to, for example, if you need to improve efficiency or to get around the error handling or formatting built into iostreams.
A streambuf consists of a stream or sequence of characters and one or two pointers into that sequence. Each pointer points between two characters. (Pointers cannot actually point between characters, but it is helpful to think of them that way.) There are two kinds of streambuf pointers:
A put pointer, which points just before the position where the next character will be stored
A get pointer, which points just before the next character to be fetched
A streambuf can have one or both of these pointers.
The positions of the pointers and the contents of the sequences can be manipulated in various ways. Whether or not both pointers move when manipulated depends on the kind of streambuf used. Generally, with queue-like streambufs, the get and put pointers move independently; with file-like streambufs the get and put pointers always move together. A strstream is an example of a queue-like stream; an fstream is an example of a file-like stream.
You never create an actual streambuf object, but only objects of classes derived from class streambuf. Examples are filebuf and strstreambuf, which are described in man pages filebuf(3CC4) and ssbuf(3), respectively. Advanced users may want to derive their own classes from streambuf to provide an interface to a special device or to provide other than basic buffering. Man pages sbufpub(3CC4) and sbufprot(3CC4) discuss how to do this.
Apart from creating your own special kind of streambuf, you may want to access the streambuf associated with an iostream to access the public member functions, as described in the man pages referenced above. In addition, each iostream has a defined inserter and extractor which takes a streambuf pointer. When a streambuf is inserted or extracted, the entire stream is copied.
Here is another way to do the file copy discussed earlier, with the error checking omitted for clarity:
ifstream fromFile("thisFile"); ofstream toFile ("thatFile"); toFile << fromFile.rdbuf();
We open the input and output files as before. Every iostream class has a member function rdbuf that returns a pointer to the streambuf object associated with it. In the case of an fstream, the streambuf object is type filebuf. The entire file associated with fromFile is copied (inserted into) the file associated with toFile. The last line could also be written like this:
fromFile >> toFile.rdbuf();
The source file is then extracted into the destination. The two methods are entirely equivalent.