Skip to content. Skip to navigation

ICTP Portal

Sections
You are here: Home Manuals on-line PGI Compiler pgC_lib stdlibug 2.5 File Input/Output
Personal tools
Document Actions

2.5 File Input/Output



Click on the banner to return to the user guide home page.

2.5 File Input/Output

File streams allow input and output to files. Unlike the C stdio functions for file I/O, however, file streams follow Stroustrup's idiom: "Resource acquisition is initialization."[25] In other words, file streams provide an advantage in that you can open a file on construction of a stream, and the file will be closed automatically on destruction of the stream. Consider the following code:

void use_file(const char* fileName)
{
   FILE* f = fopen("fileName", "w");
   // use file
   fclose(f);
}

If an exception is thrown while the file is in use here, the file will never be closed. With a file stream, however, the file will be closed whenever the file stream goes out of scope, as in the following example:

void use_file(const char* fileName)
{
   ofstream f("fileName");
   // use file
}

Here the file will be closed even if an exception occurs during use of the open file.

There are three class templates that implement file streams: basic_ifstream <charT,traits>, basic_ofstream <charT,traits>, and basic_fstream <charT,traits>. These templates are derived from the stream base class basic_ios <charT, traits>. Therefore, they inherit all the functions for formatted input and output described in Section 2.3, as well as the stream state. They also have functions for opening and closing files, and a constructor that allows opening a file and connecting it to the stream. For convenience, there are the regular typedefs ifstream, ofstream, and fstream, with wifstream, wofstream, and wfstream for the respective tiny and wide character file streams.

The buffering is done through a specialized stream buffer class, basic_filebuf <charT,traits>.

2.5.1 The Difference between Predefined File Streams (cin, cout, cerr, and clog) and File Streams

The main differences between a predefined standard stream and a file stream are:

  • A file stream needs to be connected to a file before it can be used. The predefined streams can be used right away, even in static constructors that are executed before the main() function is called.

  • You can reposition a file stream to arbitrary file positions. This usually does not make any sense with the predefined streams, as they are connected to the terminal by default.

2.5.2 Code Conversion in Wide Character Streams

In a large character set environment, a file is assumed to contain multibyte characters. To provide the contents of a such a file as a wide character sequence for internal processing, wifstream and wofstream perform corresponding conversions. The actual conversion is delegated to the file buffer, which relays the task to the imbued locale's code conversion facet.

2.5.3 File Streams

2.5.3.1 Creating and Opening File Stream Objects

There are two ways to create a file stream: you can create an empty file stream, open a file, and connect it to the stream later on; or you can open the file and connect it to a stream at construction time. These two procedures are demonstrated in the two following examples, respectively:

ifstream file;                                                \\1
_;
file.open(argv[1]);                                           \\2
if (!file) // error: unable to open file for input

or:

ifstream source("src.cpp");                                   \\3
if (!source) // error: unable to open src.cpp for input
//1A file stream is created that is not connected to any file. Any operation on the file stream will fail.
//2Here a file is opened and connected to the file stream. If the file cannot be opened, ios_base::failbit will be set; otherwise, the file stream is now ready for use.
//3Here the file is both opened and connected to the stream.

2.5.3.2 Checking a File Stream's Status

Generally you can check whether the attempt to open a file was successful by examining the stream state afterwards; failbit will be set in case of failure.

There is also a function called is_open()that indicates whether a file stream is connected to an open file. This function does not mean that a previous call to open() was successful. To understand the subtle difference, consider the case of a file stream that is already connected to a file. Any subsequent call to open() will fail, but is_open() will still return true, as shown in the following code:

void main(int argc, char* argv[])
{
  if (argc > 2)
  {  ofstream fil;                                            //1
     fil.open(argv[1]);
     // ...
     fil.open(argv[2]);                                       //2
     if (fil.fail())                                          //3
     {  // open failed  }
     if (fil.is_open())                                       //4
     {  // connected to an open file  }
}
//1Open a file and connect the file stream to it.
//2Any subsequent open on this stream will fail.
//3Hence the failbit will be set.
//4However, is_open() still returns true, because the file stream still is connected to an open file.

2.5.3.3 Closing a File Stream

In the example above, it would be advisable to close the file stream before you try to connect it to another file. This is done implicitly by the file streams destructor in the following:

void main(int argc, char* argv[])
{
  if (argc > 2)
  {  ofstream fil;
     fil.open(argv[1]);
     // ...
  }                                                           //1
  {  ofstream fil;
     fil.open(argv[2]);
    // ...
  }
}
//1Here the file stream fil goes out of scope and the file it is connected to will be closed automatically.

You can explicitly close the connected file. The file stream is then empty, until it is reconnected to another file:

ifstream f;                                                   //1
for (int i=1; i<argc; ++i)
{
    f.open(argv[i]);                                          //2
    if (f)                                                    //3
    {
        process(f);                                           //4
        f.close();                                            //5
    }
    else
        cerr << "file " << argv[i] << " cannot be opened.\n";
}
//1An empty file stream is created.
//2A file is opened and connected to the file stream.
//3Here we check whether the file was successfully opened. If the file could not be opened, the failbit would be set.
//4Now the file stream is usable, and the file's content can be read and processed.
//5Close the file again. The file stream is empty again.

2.5.4 The Open Mode

There may be times when you want to modify the way in which a file is opened or used in a program. For example, in some cases it is desirable that writes append to the end of a file rather than overwriting the existing values. The file stream constructor takes a second argument, the open mode, that allows such variations to be specified. Here is an example:

fstream Str("inout.txt",
            ios_base::in|ios_base::out|ios_base::app);

2.5.4.1 The Open Mode Flags

The open mode argument is of type ios_base::openmode, which is a bitmask type like the format flags and the stream state. The following bits are defined in Table 7:

Table 7: Flag names and effects

Flag Names
Effects
ios_base::in
Open file for reading
ios_base::out
Open file for writing
ios_base::ate
Start position is at file end
ios_base::app
Append file; i.e., always writes to the end of the file
ios_base::trunc
Truncate file; i.e., delete file content
ios_base::binary
Binary mode
in and out Open Modes">

The in and out Open Modes

Input (and output) file streams always have the in (or out) open mode flag set implicitly. An output file stream, for instance, knows that it is in output mode and you do not have to set the output mode explicitly. Instead of writing:

ofstream Str("out.txt",ios_base::out|ios_base::app);

you can simply say:

ofstream Str("out.txt",ios_base::app);

Bidirectional file streams, on the other hand, do not have the flag set implicitly. This is because a bidirectional stream does not have to be in both input and output mode in all cases. You might want to open a bidirectional stream for reading only or writing only. Bidirectional file streams therefore have no implicit input or output mode. You always have to set a bidirectional file stream's open mode explicitly.

ate, app, and trunc">

The Open modes ate, app, and trunc

Each file maintains a file position that indicates the position in the file where the next byte will be read or written. When a file is opened, the initial file position is usually at the beginning of the file. The open modes ate (meaning at end) and app (meaning append) change this default to the end of the file.

There is a subtle difference between ate and app mode. If the file is opened in append mode, all output to the file is done at the current end of the file, regardless of intervening repositioning. Even if you modify the file position to a position before the file's end, you cannot write there. With at-end mode, you can navigate to a position before the end of file and write to it.

If you open an already existing file for writing, you usually want to overwrite the content of the output file. The open mode trunc (meaning truncate) has the effect of discarding the file content, in which case the initial file length is set to zero. Therefore, if you want to replace a file's content rather than extend the file, you have to open the file in out|trunc.[27] Note that the file position will be at the beginning of the file in this case, which is exactly what you expect for overwriting an output file.

If you want to extend an output file, you open it in at-end or append mode. In this case, the file content is retained because the trunc flag is not set, and the initial file position is at the file's end. However, you may additionally set the trunc flag; the file content will be discarded and the output will be done at the end of an empty file.

Input mode only works for files that already exist. Otherwise, the stream construction will fail, as indicated by failbit set in the stream state. Files that are opened for writing will be created if they do not yet exist. The constructor only fails if the file cannot be created.

binary Open Mode">

The binary Open Mode

The binary open mode is explained in section 2.5.4.3.

2.5.4.2 Combining Open Modes

The effect of combining these open modes is similar to the mode argument of the C library function fopen(name,mode). Table 8 gives an overview of all permitted combinations of open modes for text files and their counterparts in C stdio. Combinations of modes that are not listed in the table (such as both trunc and app) are invalid, and the attempted open() operation will fail.

Table 8: Open modes and their C stdio counterparts

Open Mode
C stdio
Equivalent
Effect
in
"r"
Open text file for reading only
out|trunc
out
"w"
Truncate to zero length, if existent, or create text file for writing only
out|app
"a"
Append; open or create text file only for writing at end of file
in|out
"r+"
Open text file for update (reading and writing)
in|out|trunc
"w+"
Truncate to zero length, if existent, or create text file for update
in|out|app
"a+"
Append; open or create text file for update, writing at end of file

2.5.4.3 Default Open Modes

The open mode parameter in constructors and open() functions of file stream classes have a default value. The default open modes are listed in Table 9. Note that abbreviations are used; e.g., ifstream stands for basic_ifstream <charT,traits>.

Table 9: Default open modes

File Stream
Default Open Mode
ifstream
in
ofstream
out
fstream
in|out

2.5.5 Binary and Text Mode

The representation of text files varies among operating systems. For example, the end of a line in a UNIX environment is represented by the linefeed character '\n'. On PC-based systems, the end of the line consists of two characters, carriage return '\r' and linefeed '\n'. The end of the file differs as well on these two operating systems. Peculiarities on other operating systems are also conceivable.

To make programs more portable among operating systems, an automatic conversion can be done on input and output. The carriage return or linefeed sequence, for example, can be converted to a single '\n' character on input; the '\n' can be expanded to "\r\n" on output. This conversion mode is called text mode, as opposed to binary mode. In binary mode, no such conversions are performed.

The mode flag ios_base::binary has the effect of opening a file in binary mode. This has the effect described above; in other words, all automatic conversions, such as converting "\r\n" to '\n', will be suppressed. [28]

If you have to process a binary file you should always set the binary mode flag, because most likely you will not want any kind of implicit, system-specific conversion being performed.

The effect of the binary open mode is frequently misunderstood. It does not put the inserters and extractors into a binary mode, and hence suppress the formatting they usually perform. Binary input and output is done solely by basic_istream <charT> ::read() and basic_ostream <charT> ::write().


©Copyright 1996, Rogue Wave Software, Inc.


Powered by Plone This site conforms to the following standards: