C++ File Input/Output
Practical C++ Programming, 2nd Edition
By Steve Oualline
http://www.oreilly.com/catalog/cplus2/?CMP=OT16469
O'Reilly & Associates, December 2002
ISBN: 0-596-00419-2
Chapter 16: File Input/Output
I am the heir of all the ages, in the foremost files of time.
--Tennyson
A file is a collection of related data. C++ treats a file as a series of bytes. Many files reside on disk; however, devices such as printers, magnetic tapes, and communication lines are also considered files.
This chapter discusses three different I/O packages. The first is the C++ I/O stream classes. This is the most commonly used I/O system and the one we've been using up to now. Next, we examine the raw I/O routines that give us direct access to the low-level I/O. Finally we look at the C I/O system. Although it is somewhat outdated, C I/O calls still appear in old code. Also, in some cases, the C-style I/O routines are superior to the ones provided with C++.
C++ File I/O
C++ file I/O is based on three classes: the istream class for input, the ostream class for output, and the iostream class for input/output. C++ refers to files as streams since it considers them a stream of bytes. Four class variables are automatically created when you start a program. These are listed in Table 16-1.
|
Variable |
Use |
|---|---|
|
cin |
Console input (standard input) |
|
cout |
Console output (standard output) |
|
cerr |
Console error (standard error) |
|
clog |
Console log |
These variables are defined in the standard include file <iostream>. Normally, std::cin is assigned to the keyboard and std::cout, std::cerr, and std::clog are assigned to the screen. Most operating systems allow you to change these assignments through I/O redirection (see your operating system manual for details).
For example, the command:
my_prog <file.in
runs the program my_prog and assigns std::cin to the file file.in.
When doing I/O to disk files (except through redirection), you must use the file version of the stream classes. These are std::ifstream, std::ofstream, and std::fstream and are defined in the include file <fstream>.
Suppose you want to read a series of 100 numbers from the file numbers.dat. You start by declaring the input file variable:
std::ifstream data_file; // File we are reading the data from
Next you need to tell C++ what disk file to use. This is done through the open member function:
data_file.open("numbers.dat");
Now you can read the file using the same statements you've been using to read std::cin:
for (i = 0; i < 100; ++i) {assert(i >= 0);assert(i < sizeof(data_array)/sizeof(data_array[0]));data_file >> data_array[i];}
Finally you need to tell the I/O system that you are done with the file:
data_file.close( );
Closing the file frees resources that can then be used again by the program.
C++ allows the open call to be combined with the constructor. For example, instead of writing:
std::ifstream data_file; // File we are reading the data fromdata_file.open("numbers.dat");
you can write:
std::ifstream data_file("numbers.dat"); // File we are reading the data from
Additionally, the destructor automatically calls close.
But what if the file numbers.dat is missing? How can you tell if there is a problem? The member function bad returns true if there is a problem, and false otherwise. So to test for problems, all you need is:
if (data_file.bad( )) {std::cerr << "Unable to open numbers.dat\n";exit (8);}
A better version of the program for reading numbers is listed in Example 16-1.
Example 16-1: read/read.cpp
/********************************************************* read -- read in 100 numbers and sum them ** ** Usage: ** read ** ** Numbers are in the file "numbers.dat" ** ** Warning: No check is made for a file with less than ** 100 numbers in it. *********************************************************/#include <iostream>#include <fstream>#include <cstdlib>int main( ){const int DATA_SIZE = 100; // Number of items in the dataint data_array[DATA_SIZE]; // The datastd::ifstream data_file("numbers.dat"); // The input fileint i; // Loop counterif (data_file.bad( )) {std::cerr << "Error: Could not open numbers.dat\n";exit (8);}for (i = 0; i < DATA_SIZE; ++i) {assert(i >= 0);assert(i < sizeof(data_array)/sizeof(data_array[0]));data_file >> data_array[i];}int total; // Total of the numberstotal = 0;for (i = 0; i < DATA_SIZE; ++i) {assert(i >= 0);assert(i < sizeof(data_array)/sizeof(data_array[0]));total += data_array[i];}std::cout << "Total of all the numbers is " << total << '\n';return (0);}
If you want to read a line of data, you need to use the getline function. It is defined as:[1]
std::istream& getline(std::istream& input_file,std::string& the_string);std::istream& getline(std::istream& input_file,std::string& the_string, char delim)
This function reads a line and stores it in a string. The function returns a reference to the input stream. The second form of the function allows you to specify your own end-of-line delimiter. If this is not specified, it defaults to newline ('\n').



Solid state disks (SSDs) made a splash in consumer technology, and now the technology has its eyes on the enterprise storage market. Download this eBook to see what SSDs can do for your infrastructure and review the pros and cons of this potentially game-changing storage technology.