简体   繁体   中英

When will ofstream::open fail?

I am trying out try, catch, throw statements in C++ for file handling, and I have written a dummy code to catch all errors. My question is in order to check if I have got these right, I need an error to occur. Now I can easily check infile.fail() by simply not creating a file of the required name in the directory. But how will I be able to check the same for outfile.fail() ( outfile is ofstream where as infile is ifstream ). In which case, will the value for outfile.fail() be true?

sample code [from comments on unapersson's answer, simplified to make issue clearer -zack]:

#include <fstream>
using std::ofstream;

int main() 
{
    ofstream outfile;
    outfile.open("test.txt");
    if (outfile.fail()) 
        // do something...... 
    else 
        // do something else..... 
    return 0; 
}

The open(2) man page on Linux has about 30 conditions. Some intresting ones are:

  • If the file exists and you don't have permission to write it.
  • If the file doesn't exist, and you don't have permission (on the diretory) to create it.
  • If you don't have search permission on some parent directory.
  • If you pass in a bogus char* for the filename.
  • If, while opening a device file, you press CTRL-C.
  • If the kernel encountered too many symbolic links while resolving the name.
  • If you try to open a directory for writing.
  • If the pathname is too long.
  • If your process has too many files open already.
  • If the system has too many files open already.
  • If the pathname refers to a device file, and there is no such device in the system.
  • If the kernel has run out of memory.
  • If the filesystem is full.
  • If a component of the pathname is not a directory.
  • If the file is on a read-only filesystem.
  • If the file is an executable file which is currently being executed.

By default, and by design, C++ streams never throw exceptions on error. You should not try to write code that assumes they do, even though it is possible to get them to. Instead, in your application logic check every I/O operation for an error and deal with it, possibly throwing your own exception if that error cannot be dealt with at the specific place it occurs in your code.

The canonical way of testing streams and stream operations is not to test specific stream flags, unless you have to. Instead:

ifstream ifs( "foo.txt" );

if ( ifs ) {
   // ifs is good
}
else {
   // ifs is bad - deal with it
}

similarly for read operations:

int x;
while( cin >> x ) {
     // do something with x
}

// at this point test the stream (if you must)
if ( cin.eof() ) {
     // cool - what we expected
}
else {
     // bad 
}

To get ofstream::open to fail, you need to arrange for it to be impossible to create the named file. The easiest way to do this is to create a directory of the exact same name before running the program. Here's a nearly-complete demo program; arranging to reliably remove the test directory if and only if you created it, I leave as an exercise.

#include <iostream>
#include <fstream>
#include <sys/stat.h>
#include <cstring>
#include <cerrno>

using std::ofstream;
using std::strerror;
using std::cerr;

int main() 
{
    ofstream outfile;

    // set up conditions so outfile.open will fail:
    if (mkdir("test.txt", 0700)) {
        cerr << "mkdir failed: " << strerror(errno) << '\n';
        return 2;
    }

    outfile.open("test.txt");
    if (outfile.fail()) {
        cerr << "open failure as expected: " << strerror(errno) << '\n';
        return 0;
    } else {
        cerr << "open success, not as expected\n";
        return 1;
    }
}

There is no good way to ensure that writing to an fstream fails. I would probably create a mock ostream that failed writes, if I needed to test that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM