Apache C++ Standard Library User's Guide

## 30.3 The Open Mode

There may be times when you want to modify the way 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 that creates a file stream object `Str`, connects it to the external file named `"inout.txt"`, and opens it for reading and for writing at the end of the file:

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

Note that if the `"inout.txt"` file doesn't exist it will be created.

### 30.3.1 The Open Mode Flags

The open mode argument is of type `std::ios_base::openmode`, which is a bitmask type like the format flags and the stream state. Table 32 defines the following bits:

#### Table 32: 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; that is, always write to the end of the file
`ios_base::trunc` | Truncate file; that is, delete file content
`ios_base::binary` | Binary mode

#### 30.3.1.1 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 need not set the output mode explicitly. Instead of writing:

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

you can simply say:

    std::ofstream Str("out.txt", std::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 must always set a bidirectional file stream's open mode explicitly.

#### 30.3.1.2 The Open modes ate, app, and trunc

Each file maintains a single 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 `std::ios_base::ate` (meaning at end) and `std::ios_base::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 `ate` 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 `std::ios_base::trunc` (meaning truncate) has the effect of discarding the file content, in which case the initial file length is set to `0`. Therefore, if you want to replace a file's content rather than extend the file, you must open the file in `std::ios_base::out | std::ios_base::trunc`. Note that the file position is at the beginning of the file in this case, which is exactly what you expect for overwriting an output file.

> NOTE -- For output file streams the open mode `out` is equivalent to `out|trunc`, that is, you can omit the`trunc` flag. For bidirectional file streams, however, `trunc` must always be explicitly specified.

If you want to extend an output file, you open it with the bitwise `or` of `std::ios_base::ate` and `std::ios_base::app` 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 is discarded and the output is done at the end of an empty file.

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

#### 30.3.1.3 The binary Open Mode

The `std::ios_base::binary` open mode is discussed in Section 30.4.

### 30.3.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 33 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 fails.

#### Table 33: 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 `0` 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 `0` 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

### 30.3.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 34.

#### Table 34: Default open modes

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