13.4 Creating iostreams

To read or write a stream other than the predefined iostreams, you need
to create your own iostream. In general, that means creating objects of types
defined in the iostream library. This section discusses the various types available.

13.4.1 Dealing With Files Using Class fstream

Dealing with files is similar to dealing with standard input and standard output;
classes ifstream, ofstream, and fstream are derived from classes istream, ostream, and iostream,
respectively. As derived classes, they inherit the insertion and extraction operations (along with the
other member functions) and also have members and constructors for use with files.

Include the file fstream.h to use any of the fstreams. Use an ifstream
when you only want to perform input, an ofstream for output only, and an
fstream for a stream on which you want to perform both input and
output. Use the name of the file as the constructor argument.

For example, copy the file thisFile to the file thatFile as in
the following example:

ifstream fromFile("thisFile");
if (!fromFile)
error("unable to open ’thisFile’ for input");
ofstream toFile ("thatFile");
if (!toFile)
error("unable to open ’thatFile’ for output");
char c;
while (toFile && fromFile.get(c)) toFile.put(c);

This code does the following:

Creates an ifstream object called fromFile with a default mode of ios::in and connects it to thisFile. It opens thisFile.

Checks the error state of the new ifstream object and if it is in a failed state, calls the error function, which must be defined elsewhere in the program.

Creates an ofstream object called toFile with a default mode of ios::out and connects it to thatFile.

Checks the error state of toFile as above.

Creates a char variable to hold the data while it is passed.

Copies the contents of fromFile to toFile one character at a time.

Note - Copying a file this way, one character at a time, is, of course, undesirable. This code is provided merely as an example of using fstreams. You should instead insert the streambuf associated with the input stream into the output stream. See 13.10 Working Withstreambuf Streams, and the sbufpub(3CC4) man page.

13.4.1.1 Open Mode

The mode is constructed by or-ing together bits from the enumerated type open_mode,
which is a public type of class ios and has the following definition:

13.4.1.4 Opening a File Using a File Descriptor

If you know a file descriptor, such as the integer 1 for standard
output, you can open it as follows:

ofstream outfile;
outfile.attach(1);

When you open a file by providing its name to one of
the fstream constructors or by using the open function, the file is automatically closed
when the fstream is destroyed by a delete or when it goes out
of scope. When you attach a file to an fstream, it is
not automatically closed.

13.4.1.5 Repositioning Within a File

You can alter the reading and writing position in a file. Several
tools are supplied for this purpose.

streampos is a type that can record a position in an iostream.

tellg(tellp) is an istream(ostream) member function that reports the file position. Because istream and ostream are the parent classes of fstream, tellg and tellp can also be invoked as a member function of the fstream class.

seekg(seekp) is an istream(ostream) member function that finds a given position.

The seek_direnum specifies relative positions for use with seek.

enum seek_dir {beg=0, cur=1, end=2};

For example, given an fstreamaFile:

streampos original = aFile.tellp(); //save current position
aFile.seekp(0, ios::end); //reposition to end of file
aFile << x; //write a value to file
aFile.seekp(original); //return to original position

seekg (seekp) can take one or two parameters. When it has two parameters, the first is a position relative to the position indicated by the seek_dir value given as the second parameter. For example:

aFile.seekp(-10, ios::end);

moves to 10 bytes from the end while

aFile.seekp(10, ios::cur);

moves to 10 bytes forward from the current position.

Note - Arbitrary seeks on text streams are not portable, but you can always return to a previously saved streampos value.