CSE 202: Computer Science II, Winter 2018
File I/O

The standard C++ I/O library provides a collection of headers for performing I/O. I/O stands for input/output, it refers to any process of data communication involving a machine or computer.

In this library, I/O is performed through high-level input/output interfaces known as streams. Up to this point, you have already been using 2 predefined streams in C++: std::cin and std::cout; their types are std::istream and std::ostream, respectively. As you can guess, istream stands for "input stream" and ostream stands for "output stream". There is also a 3rd type of stream named iostream.

The header <fstream> contains std::fstream, a class for performing I/O on files.

Here is a simple program that displays the contents of a file specified as a command-line argument:

#include <iostream> #include <fstream> using namespace std; int main(int argc, char* argv[]) { if (argc != 2) { cout << "Usage: " << argv[0] << " FILENAME" << endl; return 1; } char c; fstream fs(argv[1], fstream::in); while (fs.get(c)) cout.put(c); return 0; }

In the declaration statement fstream fs(argv[1], fstream::in), we are creating a file stream object named fs; the values argv[1] and fstream::in, being used for the direct-initialization of this object, are for supplying the file name and open mode for this file stream.

When a file stream is initialized with a file name and open mode, the stream will attempt to open the specified file from the computer's file system. The open mode specifies the way this file should be opened. In our example, fstream::in means to open the file for input only.

After a file stream is initialized with fstream::in, input operations can be performed on the stream but no output operations are allowed. Input operations include the use of: the get member function, the getline function, and the stream extraction operators.

Here's another example that uses a different open mode: fstream::app. This simple program will append one line of user input to a file named "memos.txt":

#include <iostream> #include <fstream> #include <string> using namespace std; int main() { string memo; fstream fs("memos.txt", fstream::app); if (!getline(cin, memo)) return 1; fs << memo << endl; return 0; }

Once you know the different ways to open a file, using a file stream is, is for the most part, the same as using std::cin or std::cout.

Here some commonly used open modes for fstream (for a full list of open modes see the std::basic_filebuf::open page from cppreference.com):

Open mode Meaning
fstream::in Open the file for input starting at the beginning of the file
fstream::out Create the file for output starting at the beginning of the file. If the file already exists, delete it first.
fstream::app Open or create the file for output starting at the end of the file

It is possible to open a file for both input and output, but you will not be required to do so in this course.

An fstream object does not need to be associated with a file as soon as it's declared. An fstream variable can be declared with no initializer and later it can be associated with a file using the open member function. It may also be disassociated from a file using the close member function. This means you can use one fstream object to perform I/O on different files throughout the duration of the program.

Here is a variation of the first fstream example, it takes multiple command-line argument file names and outputs the contents of each of them to standard output:

#include <iostream> #include <fstream> using namespace std; int main(int argc, char* argv[]) { char c; fstream fs; for (size_t i = 1; i < argc; ++i) { fs.open(argv[i], fstream::in); while (fs.get(c)) cout.put(c); fs.close(); } return 0; }

The significance of this example is that one file stream object was used yet multiple files were opened and read in this program.

Notice how fstream::close is called in this example, but it was not called in previous examples. This is because file stream objects automatically call the close member function during their destruction.

There is an fstream member function named is_open, when called with no arguments, it returns true if the stream is associated with an open file; the return value can be false if a previous open operation failed to open the file.

In the above code examples, is_open is not necessary to use since the while loops with I/O operations as conditions will fail anyways if the file failed to open.