In a C++ program, using std::ifstream, I'm attempting to open a user-specified file -- so far so good. However, I accidentally entered a filename that's actually a directory, and I was quite surprised to see that attempting to open() that directory didn't generate any errors.
Here's a minimal example:
std::ifstream f;
f.open("..");
if(!f.is_open() || !f.good() || f.bad() || f.fail()) {
std::cout << "error bit set on open" << std::endl;
return 1;
}
No sign of error here. If I go on and attempt to getline(), getline() sets an error bit all right.
std::string str;
getline(f, str);
if(f.eof()) std::cout << "getline set eofbit" << std::endl;
else if(f.bad()) std::cout << "getline set badbit" << std::endl;
else if(f.fail()) std::cout << "getline set failbit" << std::endl;
This outputs "getline set badbit", which is reasonable. Using the >> operator throws an underflow exception, which is also okay.
Now, my question is, how could I detect that the user entered a directory name instead of a proper filename? Is there any way to do that? Getting and ungetting bytes from the stream seem tedious and error-prone.
Also, why is this so? I realize that it's all just the same data from the point of view of the program, but I'd assume the OS would also send some "hey, this is a directory" kind of message.
The exception will be thrown when you encounter the EOF because you set ifstream::failbit as exception mask, at least on Mac OS 10.10 Yesomite. If a file is read when EOF is encountered, ios_base::failbit will be set together with ios_base::eofbit .
Opening a File Either ofstream or fstream object may be used to open a file for writing. And ifstream object is used to open a file for reading purpose only. Following is the standard syntax for open() function, which is a member of fstream, ifstream, and ofstream objects.
So no, we do not need to explicitly call fstream::close() to close the file. After open a file with fstream/ifstream/ofstream, it is safe to throw an exception without manually close the file first.
An ifstream variable has an open function which can be used to open a file. The name of the file is a parameter to the open function. Once this is done, you can read from the ifstream object in exactly the same way you would read from cin.
You don't say what your system is, so it's hard to say, but generally,
filebuf::open
will only return an error if your system level open
fails. And I've worked on Unix systems where you could open()
a
directory; I've even worked on some where you could read it after the
open (at least if it was a locally mounted filesystem).
As to what to do about it: about all I can think of is to try to get
the first character, then put it back. But this fails if the file is
empty, so it's not really a solution either. At the system level (and
from a QoI point of view, I'd expect filebuf::open
to do this if the
system did allow opening a directory), you can use a system level call
(stat
in Unix) to determine whether the file is a directory or not.
(There's a race condition, of course: between the moment you detect that
it's a normal file, and the moment you do the open, another process
could delete the file and create a directory. It's probably not a
frequent occurance, however.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With