Consider the following code:
ifstream in;
try {
in.exceptions ( ifstream::failbit | ifstream::badbit );
in.open(pConfLocation);
} catch ( ifstream::failure e ) {
throw std::runtime_error("Can't open configuration file\n");
}
vector<string> lns;
string s;
in.clear();
while ( !in.eof() ){
getline( in, s );
boost::algorithm::trim(s);
lns.push_back( s+='\n');
}
So:
- I set the following “exception mask” ( ifstream::failbit | ifstream::badbit ) for the needs of the try-catch block. The file opens without problems.
- In while{} block, I know that at the end of the file eofbit will be set. But
The exception mask is an internal value of all stream objects
specifying which state flags have to throw an exception when they are
set.
I did NOT set ifstream::eofbit, but anyway the following error appears at runtime:
terminate called after throwing an instance of 'std::ios_base::failure'
what(): basic_ios::clear
The program has unexpectedly finished.
I cannot understand this behavior. I tried to use in.clear() right before while{} but with no effect. clear() itself sets goodbit, and as far as I understand, “flags have to throw an exception” (see the quote above), but when googbit set it’s not causing to throw any exceptions…
If to delete
in.exceptions ( ifstream::failbit | ifstream::badbit );
it works.
How to make getline() work in this case?
The problem is in your input iteration.
eofbitis only set when the last read reached EOF, not if the next read will read only EOF. When the latter happens,failbitis set at the same time. See the discussion here.In your particular case, if the file ends with a newline (as it probably does), the
getline()reads up to and including that newline and returns.eofbitis still not set. The nextgetline()then encounters EOF directly, and as per its documentation, “If the function extracts no elements, it callssetstate(failbit).”