Reputation: 8310
Why does ifstream
set the failbit
to 1
after reading the last line of the specified file? How do I know if the specified file has been read correctly?
bool read_csv_file(const char* filename, vector<string>& lines, bool adding = false)
{
if( !adding ) lines.clear();
ifstream csvfile;
csvfile.open(filename);
if( csvfile.is_open() )
{
string line;
while( csvfile.good() && getline(csvfile,line) )
{
lines.push_back(line);
cout << "fail: " << csvfile.fail() << endl;
}
cout << "fail: " << csvfile.fail() << endl;
csvfile.close();
return (!csvfile.fail());
}
return false;
}
Upvotes: 0
Views: 281
Reputation: 153899
The only reason failbit
could be set after reading the last
line (or any line) is if there were an error in the library, and
I don't really believe it. If failbit
is set, it means that
you didn't read anything. In your case, it will never be set
when you're in the loop; if it were set, getline
would have
evaluated to false
, and you wouldn't have entered the loop.
And of course, the loop terminates precisely because getline
fails (or would fail—normally, you would not test for
good
before doing input, and if you do, consider that the
failbit
was set, regardless, if the test fails).
The usual pattern for this sort of thing is:
while ( someInput ) {
// ...
}
if ( csvfile.bad() ) {
// Serious error (disk read error, etc.)...
} else if ( ! csvfile.eof() ) {
// Formatting error...
} else {
// Normal end of file...
}
When someInput
is std::getline()
, however, you will never
fail because of a formatting error, so the else if
above will
never be true (and a lot of code treats hard disk errors as if
they were an end of file, and so ignores the if
part as well).
Upvotes: 1
Reputation: 1569
Too check for erroneous reads, you must test badbit
using stream.bad()
.
Failbit
indicates failure in operation logic, and apparently getline
sets it when reaching EOF (confirmed on my machine).
Upvotes: 1
Reputation: 476940
The fail bit is set after you run off the end of the file. Once that happens, you mustn't attempt to interpret the result of your input operation. That's perfectly fine, though, and getline
will not set the fail bit while there's still any data to be read. So the following standard loop extracts all the lines:
for (std::string line; std::getline(csvfile, line); )
{
// process "line"
}
// all done
Upvotes: 2