I l@ve RuBoard |
![]() ![]() |
16.1 C++ File I/OC++ 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.
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 from data_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 data int data_array[DATA_SIZE]; // The data std::ifstream data_file("numbers.dat"); // The input file int i; // Loop counter if (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 numbers total = 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'). 16.1.1 Reading C-Style StringsTo read C-style strings, you can use the getline function. (This is an overload version of the getline function discussed in the previous section.) This getline member function is defined as: std::istream& getline(char *buffer, int len, char delim = '\n') The parameters to this function are:
This function returns a reference to the input file. The function reads up to and including the end-of-line character ('\n'). The end-of-line character is not stored in the buffer. (An end-of-string ('\0') is store in to terminate the string.) For example: char buffer[30]; std::cin.getline(buffer, sizeof(buffer)); 16.1.2 Output FilesThe functions for output files are similar to input files. For example, the declaration: std::ofstream out_file("out.dat"); creates a file named out.dat and lets you write to the file using the file variable out_file. Actually, the constructor can take two additional arguments. The full definition of the output file constructor is: std::ofstream::ofstream(const char *name, int mode=std::ios::out, int prot = filebuf::openprot); The parameters for this function are:
For example, the statement: std::ofstream out_file("data.new", std::ios::out|std::ios::binary|std::ios::nocreate| std::ios::app); appends (std::ios::app) binary data (std::ios::binary) to an existing file (std::ios::nocreate) named data.new. Example 16-2 contains a short function that writes a message to a log file. The first thing the function does is to open the file for output (std::ios::out), appending (std::ios::app), with the writing to start at the end of the file (std::ios::ate). It then writes the message and closes the file (the destructor for out_file performs the close). This function was designed to be simple, which it is. But also we didn't care about efficiency, and as a result this function is terribly inefficient. The problem is that we open and close the file every time we call log_message. Opening a file is an expensive operation, and things would go much faster if we opened the file only once and remembered that we had it open in subsequent calls. Example 16-2. log/log.cpp#include <iostream> #include <fstream> void log_message(const string& msg) { std::ofstream out_file("data.log", if (out_file.bad( )) return; /* Where do we log an error if there is no log */ out_file << msg << endl; } ![]() |
I l@ve RuBoard |
![]() ![]() |