• (3 Pages)
  • +
  • 1
  • 2
  • 3

EOF and reading text files (C++) FAQ: Why you should never use EOF while reading a text file Rate Topic: ***** 2 Votes

#31 Mister G  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 26-September 13

Posted 26 September 2013 - 08:59 AM

Wow, I'm so glad I came upon this tutorial. Your explanation was very thorough and it will help me a lot. Thanks again.
Was This Post Helpful? 0
  • +
  • -

#32 saxomania  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 06-November 13

Posted 06 November 2013 - 11:14 AM

This approach is fine - as long as one does not want to distinguish between a corrupt / false file and "there are no entries in the file". As soon as you want to be able to distinguish between an error (I now don't consider EOF as an error) and the end of the file, your approach won't work.

See what happens, when the last entry of the file got read: The while loop will not stop after the last entry was read, instead another evaluation of
istream >> mystruct
is called, within the operator>> then there are numerous calls to getline or other attempts to extract data from the stream, every such call will fail and the stream ends up not only having the eofbit but also the failbit set.

Consider the following:
std::vector<MyType> stuff;
std::ifstream ifs(path);
if (ifs.is_open()) {
    ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit); // not eofbit !!!
    try {
        MyType mytype;
        while (ifs >> mytype) {
            stuff.push_back(mytype);
        }
    }
    catch (std::ios_base::failure const& f) {
        std::cerr << "Uh, oh, something went wrong" << std::endl; // This will always happen!
        stuff.clear();
    }
}
ifs.close();



The above code will always fail, even if the file is all well, there will be an exception thrown within the operator>>, since after reading the last entry the state of the stream is still ok. At the first attempt to extract more data within operator>> an exception will be thrown.

The sad part of it: If someone wants to be able to distinguish between failbit | badbit and eofbit, we still have to check for the end of the file. The difference to other approaches concerning this: Don't ask the stream whether the eofbit has been set, instead check yourself if the next extraction will give the end of file:

std::vector<MyType> stuff;
std::ifstream ifs(path);
if (ifs.is_open()) {
    ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit); // not eofbit !!!
    try {
        MyType mytype;
        while (ifs.peek() != std::ifstream::trais_type::eof()) { // This will not extract a character and won't throw!
            ifs >> mytype; // This will throw if an error occurs during extraction
            stuff.push_back(mytype);
        }
    }
    catch (std::ios_base::failure const& f) {
        std::cerr << "Uh, oh, something went wrong" << std::endl; // If this happens, there really WAS an error (not just eof)
        stuff.clear();
    }
}
ifs.close();



The above code works and makes it possible to really distinguish between an error and the end of file. There will be no useless call to operator>> that will fail and if it fails you know there was an error.
Was This Post Helpful? 0
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3