enzom83
enzom83

Reputation: 8310

How do I know if the specified file has been read correctly?

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

Answers (3)

James Kanze
James Kanze

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

rburny
rburny

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

Kerrek SB
Kerrek SB

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

Related Questions