Flagging the ios Flags in C++ - dummies

By John Paul Mueller, Jeff Cogswell

When you open a file by constructing either an ofstream or ifstream instance, you can modify the way the file will open by supplying what are called flags. In computer terms, a flag is simply a small item whose presence or lack of presence tells a function how to do something. With the ofstream and ifstream classes, the function in question is the constructor.

A flag looks like ios::app if you’re using a compiler that is not fully ANSI-compliant, or looks like ios_base::app if you’re using one that is fully ANSI-compliant. This particular flag means that you want to write to a file, but you want to append to any existing data that may already be in a file. You supply this flag as an argument of the constructor for ofstream, as in either of the following examples:

ofstream outfile("AppendableFile.txt", ios::app);
ofstream outfile("AppendableFile.txt", ios_base::app);

You can see that the flag is added as a second parameter to the constructor. Other flags exist besides app, and you can combine them by using the or operator, |. For example, one flag is ios::nocreate (which isn’t included in newer compilers).

This one means “only open the file if it already exists.” That is, don’t create the file if it doesn’t exist. (Remember, ofstream creates a file if it doesn’t already exist.) If the file doesn’t exist, the open will fail, and when you call fail, you will get back a true.

The ios::nocreate flag is handy with ios::app. Together, these mean open an existing file and append to it. That is, the two together will work only if the file already exists, and the call will open the file for an append operation. If the file doesn’t already exist, the file won’t be created. Here’s a sample call:

ofstream outfile("../MyFile.txt", ios::app | ios::nocreate);
if (outfile.fail()) {
    cout << "Couldn't open the file!" << endl;
    return 0;
}
outfile << "Hi" << endl;
outfile.close();

If MyFile.txt doesn’t exist when you run this code, you get the message Couldn’t open the file! But if MyFile.txt does exist, the application opens it, appends the string Hi to it, and finally closes it.

It turns out that the nocreate flag is not available in the new Standard Library. Bummer. Therefore the code works only if you’re using an earlier version of the library. When using the Code::Blocks compiler, you see the following error message:

error: 'nocreate' is not a member of ';std::ios'

However, you’ll want to test whether your particular compiler includes a library that supports ios::nocreate. Your compiler may support it anyway, even if it includes the new Standard Library. As an alternative to ios::nocreate, you can use the following code (found in the FileOutput02 example):

ifstream infile("../MyFile.txt");
if (infile.fail())
{
    cout << "Couldn't open the file!" << endl;
    return 0;
}
infile.close();
ofstream outfile("../MyFile.txt", ios::app);
outfile << "Hi" << endl;
outfile.close();

In this case, you begin by attempting to open the file for reading. If the file doesn’t exist, you can’t read from it and the code exits with a failure message. If the code can read from the file, it reopens the file for writing. This is a cumbersome workaround, but it works.

Following is a list of the available flags. First, here are the ones for ios, in case you’re using a compiler that is not completely ANSI-compliant:

  • ios::app: This flag means that you want to open a file and append to it.

  • ios::in: Include this flag if you want to read from a file.

  • ios::out: Include this flag if you want to write to a file.

  • ios::trunc: Include this flag if you want to wipe out the contents of the file before writing to it. It’s the opposite of append, and it’s also the default if you don’t specifically include ios::app.

  • ios::nocreate: Use this flag if you want to ensure that the file will not be created if it doesn’t exist, resulting in the file not being opened.

  • ios::noreplace: This flag is the opposite of nocreate. Use this flag if you only want to create a new file. If you use this flag and the file already exists, the file will not open, and that failure will return true.

ANSI-compliant compilers don’t support the ios::noreplace flag either. In this case, you can use the opposite of the fix for the ios:nocreate flag, as shown here (and found in the FileOutput03 example):

ifstream infile("../MyFile.txt");
if (!infile.fail())
{
    cout << "The file already exists!" << endl;
    return 0;
}
infile.close();
ofstream outfile("../MyFile.txt");
outfile << "Hi" << endl;
outfile.close();

In this case, the code attempts to open the file for reading. If the file exists, the code shows an error message and exits. Otherwise the code creates a new file and writes to it.

The following flags are available in a complier that’s absolutely ANSI-compliant!

  • ios::ate: Use this flag to go to the end of the file after you open it. Normally, you use this flag when you want to append data to the file.

  • ios_base::binary: Use this flag to specify that the file you’re opening will hold binary data — that is, data that does not represent character strings.

  • ios_base::in: Specify this flag when you want to read from a file.

  • ios_base::out: Include this flag when you want to write to a file.

  • ios_base::trunc: Include this flag if you want to wipe out the contents of a file before writing to it.

  • ios_base::app: Include this flag if you want to append to the file. It’s the opposite of trunc — that is, the information that’s already in the file when you open it will stay there.

Why do you need an in flag and an out flag? It seems that the computer should know whether you’re writing to a file or reading from it, depending (respectively) on whether you use ofstream or ifstream. The answer to why you have an in flag and an out flag is that other classes are available besides ofstream and ifstream.

The compilers that don’t yet fully support the ANSI standard have a generic class in their libraries called fstream. The ANSI-compliant compilers have in their libraries a template class called basic_filebuf and a class called filebuf. If you use these classes, you can use the in and out flags.