fstream::exceptions unexpected behaviour
In the code below; any idea why the ifs
becomes bad when std::copy is performed?
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
int main(int argc, char* argv[]) {
std::fstream ifs(argv[1], std::fstream::in | std::fstream::binary);
std::fstream ofs(argv[2], std::fstream::out | std::fstream::trunc | std::fstream::binary);
ifs.unsetf(std::ios_base::skipws);
std::istream_iterator<unsigned char> begin(ifs);
std::istream_iterator<unsigned char> end;
std::ostream_iterator<char> begin2(ofs);
ifs.exceptions(std::fstream::badbit | std::fstream::failbit);
ofs.exceptions(std::fstream::badbit | std::fstream::failbit);
if(!ifs)
std::cerr << "ifs bad" << std::endl;
if(!ofs)
std::cerr << "ofs bad" << std::endl;
try {
std::copy(begin, end, beg开发者_高级运维in2);
}
catch(...) {
if(ifs.bad())
std::cerr << "exception: ifs bad" << std::endl;
if(ifs.fail())
std::cerr << "exception: ifs fail" << std::endl;
if(ifs.eof())
std::cerr << "exception: ifs eof" << std::endl;
}
if(!ifs)
std::cerr << "ifs bad" << std::endl;
if(!ofs)
std::cerr << "ofs bad" << std::endl;
//ofs << ifs.rdbuf();
}
Here is the output I get.
~$ cp fstream.cpp ~/tmp/fstream/
~$ g++ -ggdb -O0 fstream.cpp
~$ ./a.out a.out xxx.ooo
exception: ifs fail
exception: ifs eof
ifs bad
The (default constructed) end
iterator you've given as the place to stop copying will only compare equal to the other iterator when attempting to read the specified data from the file fails. In this case, it's converted all the data in the file and reached EOF. That means everything has succeeded, but the stream is now in a fail state, so until or unless you reset it, you won't be able to do anything else with that stream.
You've also misinterpreted things a bit: !stream
is equivalent to stream.fail()
, but that's not the same as stream.bad()
. stream.bad()
means there's been a serious failure such as a hard drive dying while you were trying to read from it. stream.fail()
can mean something much milder (or even normal) such as an attempted conversion failing, possibly because you're read some data that can't be converted to the target type (e.g., the stream contains "one" and you're trying to read an int
) or because (as in this case) you've reached the end of the file.
Bottom line: iostreams exceptions are only rarely of much use. Some of the exceptions are defined to be thrown in perfectly normal, expected cases.
精彩评论