Notes from C++ Primer
File State
Condition state is used to manage stream state, which indicates if the stream is available or recoverable.
State of stream is descripted by three member function: bad, fail, eof and good.
- bad(): unrecoverable error. If the stream state is badbit, then it can't be used again. bad() returns true.
- fail(): recoverable error. If the stream state is failbit, fail() returns true.
- eof(): when stream meets the end-of-file. eofbit will be set. Also, the stream will be set failbit at the same time.
- good(): the state of stream. If one of bad, fail, eof is true, the good will return false, otherwise return true.
There're two operations to change the condition state: clear, setstate.
- clear: reset the stream to be available.
- setstate: open one of specified condition state.
The mangement of stream can be like this:
int ival; // read cin and test only for EOF; loop is executed even if there are other IO failures while(cin >> word, !cin.eof()) { if(cin.bad()) // input stream is corrupted; bail out throw runtime_error("IO stream corrupted"); if(cin.fail()) // bad input { cerr << "bad data, try again"; // warn the user cin.clear(istream::failbit); // reset the stream continue; } // ok to process ival ... }
Member function rdstate() returns the current state of stream. The below example also display how to set the state of stream:
// remember current state of cin istream::iostate old_state = cin.rdstate(); cin.clear(); process_input(); // use cin cin.clear(old_state); // now reset cin to old state ... // sets both the badbit and the failbit is.setstate(ifstream::badbit | ifstream::failbit);
Use of File Stream
Assume ifle and ofile is the string object storing the names of input and output files' namess.
string ifile = "inputFile.txt"; string ofile = "outputFile.txt";
Then the use of file stream is like this:
// construct an ifstream and bind it to the file named ifile ifstream infile(ifile.c_str()); // ofstream output file object to write file named ofile ofstream outfile(ofile.c_str());
Also, we can define unbound input and output file stream first, and then use open function to boud the file we'll access:
ifstream infile; // unbound input file stream ofstream outfile; // unbound output file stream infile.open("in"); // open file named "in" in the current directory outfile.open("out"); // open file named "out" in the current directory
After opening the file, we need to check if it is successful being opened:
// check that the open succeeded if(!infile){ cerr << "error: unable to open input file: " << infile << endl; return -1; }
Rebound File Stream with New File
If we want to bound the fstream with another file, we need to close the current file first, and then bound with another file:
ifstream infile("in"); // open file named "in" for reading infile.close(); // closes "in" infile.open("next"); // open file named "next" for reading
Clear File Stream Status
Opening all file names in a string vector, one direct version is:
vector<string> files; ... vector<string>::const_iterator it = files.begin(); string s; // string buffer // for each file in the vector while(it != files.end()){ ifstream input(it->c_str()); // open the file // if the file is ok, read and "process" the input if(!input) break; // error: bail out! while(input >> s) // do the work on this file process(s); ++it; // increament iterator to get next file }
More efficient way but with much more accurate operation version:
ifstream input; vector<string>::const_iterator it = files.begin(); // for each file in the vector while(it != files.end()){ input.open(it->c_str()); // open the file // if the file is ok, read and "process" the input if(!input) break; // error: bail out! while(input >> s) // do the work on this file process(s); input.close(); // close file when we're done with it input.clear(); // reset state to ok ++it; }
File Mode
When you use ofstream to open file, the only way to store existing data is to set the app mode explicitly.
// output mode by default; truncates file named "file1" ofstream outfile("file1"); // equivalent effect: "file1" is explicitly truncated ofstream oufile2("file1", ofstream::out | ofstream::trunc); // append mode: adds new data at end of existing file named "file2" ofstream appfile("file2", ofstream::app);
File mode is the attribute of file, not stream
ofstream outfile; // output mode set to out, "scratchpad" truncated because of after definition outfile.open("scratchpad", ofstream::out); outfile.close(); // close outfile so we can rebind it // appends to file named "precious" outfile.open("precious", ofstream::app); outfile.close(); // output mode set by default, "out" truncated outfile.open("out");