Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get error message when ifstream open fails

ifstream f;
f.open(fileName);

if ( f.fail() )
{
    // I need error message here, like "File not found" etc. -
    // the reason of the failure
}

How to get error message as string?

like image 793
Alex F Avatar asked Oct 15 '22 07:10

Alex F


People also ask

Why is my ifstream not working?

The issue is most likely one of the following: 1) map_2. txt does not exist in the location you specified in your ifstream declaration. 2) You do not have sufficient rights to access the root folder of your C drive.

Does ifstream need to be closed?

No, this is done automatically by the ifstream destructor. The only reason you should call it manually, is because the fstream instance has a big scope, for example if it is a member variable of a long living class instance.

Is ifstream open?

std::ifstream::is_openReturns whether the stream is currently associated to a file. Streams can be associated to files by a successful call to member open or directly on construction, and disassociated by calling close or on destruction.

Does ifstream automatically close the file?

Note that any open file is automatically closed when the ifstream object is destroyed.


3 Answers

Every system call that fails update the errno value.

Thus, you can have more information about what happens when a ifstream open fails by using something like :

cerr << "Error: " << strerror(errno);

However, since every system call updates the global errno value, you may have issues in a multithreaded application, if another system call triggers an error between the execution of the f.open and use of errno.

On system with POSIX standard:

errno is thread-local; setting it in one thread does not affect its value in any other thread.


Edit (thanks to Arne Mertz and other people in the comments):

e.what() seemed at first to be a more C++-idiomatically correct way of implementing this, however the string returned by this function is implementation-dependant and (at least in G++'s libstdc++) this string has no useful information about the reason behind the error...

like image 96
Matthieu Rouget Avatar answered Oct 23 '22 05:10

Matthieu Rouget


You could try letting the stream throw an exception on failure:

std::ifstream f;
//prepare f to throw if failbit gets set
std::ios_base::iostate exceptionMask = f.exceptions() | std::ios::failbit;
f.exceptions(exceptionMask);

try {
  f.open(fileName);
}
catch (std::ios_base::failure& e) {
  std::cerr << e.what() << '\n';
}

e.what(), however, does not seem to be very helpful:

  • I tried it on Win7, Embarcadero RAD Studio 2010 where it gives "ios_base::failbit set" whereas strerror(errno) gives "No such file or directory."
  • On Ubuntu 13.04, gcc 4.7.3 the exception says "basic_ios::clear" (thanks to arne)

If e.what() does not work for you (I don't know what it will tell you about the error, since that's not standardized), try using std::make_error_condition (C++11 only):

catch (std::ios_base::failure& e) {
  if ( e.code() == std::make_error_condition(std::io_errc::stream) )
    std::cerr << "Stream error!\n"; 
  else
    std::cerr << "Unknown failure opening file.\n";
}
like image 37
Arne Mertz Avatar answered Oct 23 '22 05:10

Arne Mertz


Following on @Arne Mertz's answer, as of C++11 std::ios_base::failure inherits from system_error (see http://www.cplusplus.com/reference/ios/ios_base/failure/), which contains both the error code and message that strerror(errno) would return.

std::ifstream f;

// Set exceptions to be thrown on failure
f.exceptions(std::ifstream::failbit | std::ifstream::badbit);

try {
    f.open(fileName);
} catch (std::system_error& e) {
    std::cerr << e.code().message() << std::endl;
}

This prints No such file or directory. if fileName doesn't exist.

like image 26
rthur Avatar answered Oct 23 '22 04:10

rthur