Input and Output File

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");

 

posted @ 2015-01-27 22:17  kid551  阅读(318)  评论(0编辑  收藏  举报