Search code examples
c++fstreamifstream

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;
}

Solution

  • 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).