Is there any RAII file handle already implemented?

std::fstreams support RAII-style usage - they can be opened and even tested at construction, and they're automatically flushed and closed in the destructor, though you could miss errors if you just assume that works so you may want to do something more explicit in code if you need the robustness.

For example:

if (std::ifstream input(filename))
    ... use input...
else
    std::cerr << "unable to open '" << filename << "'\n";

If you really want to use file descriptors, you can tune something like the following to taste. It's a bit longer than something that just invokes close, but if you want to do robust programming you need to check for and handle errors somehow....

struct Descriptor
{
    Descriptor(int fd, const char* filename = nullptr)
      : fd_(fd), filename_(filename)
    {
        if (fd < 0)
        {
            std::ostringstream oss;
            oss << "failed to open file";
            if (filename_) oss << " '" << filename_ << '\'';
            oss << ": " << strerror(errno);
            throw std::runtime_error(oss.str());
        }
    }
    ~Descriptor()
    {
        if (fd_ != -1 && close(fd_) == -1)
        {
            // throwing from destructors risks termination - avoid...
            std::cerr << "failed to close file";
            if (filename_) std::cerr << " '" << filename_ << '\'';
            std::cerr << ": " << strerror(errno) << std::endl;
        }
    }
    operator int() const { return fd_; }

  private:
    int fd_;
};

Usage:

try
{
    Descriptor fd(open(filename, O_RDONLY), filename);
    int nbytes = read(fd, ...);
    ...
}
catch ...

Depends on what exactly you want.

If you really want a scoped handle, use:

std::unique_ptr<HANDLETYPE, closehandletypefunction> smartpointer;

For FILE pointers, this would look like

std::unique_ptr<FILE, int (*)(FILE *)> f(fopen("myfile.txt", "a"), fclose);

The FILE* can then be gotten with f.get(). The same thing would work with file descriptors (open and close from <fcntl.h> and <unistd.h>, respectively).

The preferred C++ way is wrapping the handle in an object with thousands of members to do everything though.


I am using boost::filesystem::ifstream (or ofstream for writing).

I was actually asking this because I wanted to be sure that my file was closed even if an exception was raised before calling file.close()

But after reading the documentation again:

In case that an object is destroyed while still associated with an open file, the destructor automatically calls the member function close.

So, this is safe :)

Tags:

C++

Io

Raii