Go to main content
Oracle® Developer Studio 12.6: C++ User's Guide

Exit Print View

Updated: July 2017
 
 

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 Working With streambuf 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:

enum open_mode {binary=0, in=1, out=2, ate=4, app=8, trunc=0x10,
     nocreate=0x20, noreplace=0x40};

Note - The binary flag is not needed on UNIX but is provided for compatibility with systems that do need it. Portable code should use the binary flag when opening binary files.

You can open a file for both input and output. For example, the following code opens file someName for both input and output, attaching it to the fstream variable inoutFile.

fstream inoutFile("someName", ios::in|ios::out);

13.4.1.2 Declaring an fstream Without Specifying a File

You can declare an fstream without specifying a file and open the file later. The following example creates the ofstream toFile for writing.

ofstream toFile;
toFile.open(argv[1], ios::out);

13.4.1.3 Opening and Closing Files

You can close the fstream and then open it with another file. For example, to process a list of files provided on the command line:

ifstream infile;
for (char** f = &argv[1]; *f; ++f) {
   infile.open(*f, ios::in);
   ...;
   infile.close();
}

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_dir enum specifies relative positions for use with seek.

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

    For example, given an fstream aFile:

    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.