views:

146

answers:

3

I'm very new to the world of C++ error handling, but I was told here:
http://stackoverflow.com/questions/3622030/checking-for-file-existence-in-c

...that the best way to checks for file existence was with a try-catch block. From my limited knowledge on the topic, this sounds like sound advice. I located this snippet of code:
http://www.java2s.com/Tutorial/Cpp/0240__File-Stream/Readafileintrycatchblock.htm

#include <fstream>
#include <iostream>
using namespace std;

int main () 
{
  try{
      char buffer[256];
      ifstream myfile ("test.txt");

      while (! myfile.eof() )
      {
        myfile.getline (buffer,100);
        cout << buffer << endl;
      }
  }catch(...){
     cout << "There was an error !\n";
  }
  return 0;
}

...but when I compile it using

g++ -Wall -pedantic -o test_prog main.cc

And run the program in a directory where test.txt does not exist, the prog keeps spitting out empty lines to the terminal. Can anyone figure out why?

Also is this a good way to check for file existence for a file you actually want to open and read from (versus just something where your indexing a bunch of files and checking them over)?

Thanks!

+1  A: 

By default the fstream objects do not throw. You need to use void exceptions ( iostate except ); to set the exception behavior. You can fetch the current settings using iostate exceptions ( ) const;. Change your code just a bit:

#include <fstream>
#include <iostream>
#include <stdexcept>
using namespace std;

int main () 
{
  try{
      char buffer[256];
      ifstream myfile ("test.txt");
      file.exceptions ( ifstream::eofbit | ifstream::failbit | ifstream::badbit );
      while (file)
      {
        myfile.getline (buffer,100);
        cout << buffer << endl;
      }
  }catch(std::exception const& e){
     cout << "There was an error: " << e.what() << endl;
  }
  return 0;
}
dirkgently
+2  A: 

In C++ iostreams do not throw exeptions by default. What you need is

ifstream myfile("test.txt");

if(myfile) {
   // We have one
}
else {
   // we dont
}
Artyom
So which is better (and why) -- this or enabling exceptions as dirkgently illustrates?
Jason R. Mick
@Jason: Don't use exceptions. Just test the file stream object.
Martin York
+3  A: 

First of all, for the try block to do any good, you need to enable exceptions for the stream.

Second, a loop like:

  while (! myfile.eof() )

Will lead to nothing but trouble, and you're seeing that here. The problem (in this case) is that when the file failed to open, eof will never be signaled -- you can't/don't reach the end of the file because there is no file. Therefore, your loop runs forever, on an existentialist search for the end of a nonexistent file. Fix the loop, and things get better in a hurry:

 char buffer[256];
 ifstream myfile ("test.txt");

 while (myfile.getline(buffer,100))
 {
   cout << buffer << endl;
 }

While you're at it, a bit more fixing wouldn't hurt (unless you really meant to use less than half of the space you allocated for your buffer):

 char buffer[256];
 ifstream myfile ("test.txt");

 while (myfile.getline(buffer,sizeof(buffer)))
 {
   cout << buffer << endl;
 }

Or, of course, eliminate the problem entirely:

std::string buffer;
ifstream myfile("test.txt");
while (getline(myfile, buffer))
    cout << buffer << "\n";

Edit: note that none of these (at least currently) depends on exceptions at all. They're all set up to write a line to the output if we succeeded in our attempt at reading a line from the input. If the file didn't open, the body of the loop simply won't execute, because we won't be able to read from a file that didn't open. If we want to print an error message telling the user that the file didn't open, we'd have to handle that separately from what's above. For example:

ifstream myfile("test.txt");

if (!myfile) {
    std::cerr << "File failed to open";
    return FAIL;
}

while (std::getline(myfile // ...
Jerry Coffin