The Boost Filesystem library

Writing a C++ function that prints to standard output the size of a file given its filename, is a more complicated job than one could expect.

This is because the C++ standard does not make available (yet) any library to shield the different approaches taken by different operating system to the file system, and so the programmers have to directly take care of the system's low level details.

Alternatively, we could use the Boost Filesystem library. By the way, this library is a candidate to be included in Technical Report 2, and so we could expect that something close to it would be eventually included in the standard.

The typical issues we have to tackle when writing code that has to do with file system are:

Are the file names written accordingly Windows or UNIX conventions (or both)?

Is the passed filename correct? I mean, does it refer to what could be an object in the referred file system?

Does that file actually exists?

Accessing to a file system is always a dangerous matter: how we could avoid the application to crash in case of an unforeseen problem?

The Boost::filesystem answer to these questions using a custom class for storing the filename and throwing exceptions (or returning an error code, if for any reason we don't want our code to use the exception facility) in case of errors.

Let see as example a possible implementation for the function we said above: it gets as input a filename, and it prints to standard console it length:
#include <iostream>
#include <boost/filesystem.hpp>

// ...

void fileSize(boost::filesystem::path filename)
{
try
{
std::cout << filename << " size: "
<< boost::filesystem::file_size(filename) << std::endl;
}
catch(const boost::filesystem::filesystem_error& ex)
{
std::cout << ex.what() << std::endl;
}
}

Amazingly concise and effective, I'd say. We try to call the Boost Filesystem file_size() function, if it succeeds, it returns a uintmax_t (the biggest unsigned integer type available for the current platform), otherwise it throws an exception.

Here is a few test calls I performed for this function:
fileSize(argv[0]); // 1.

std::string s("/dev/pl.sql"); // 2.
fileSize(s);

fileSize("/dev"); // 3.

fileSize("W:\\not\\existing.com"); // 4.

1. We pass to our function the first argument coming from the environment to the main() function, that is the filename used to invoke the application. Being compiled for Windows, it is in that format.
2. We can pass to our function C and C++ strings. Notice that here we are using the UNIX convention (forward slashes)
3. On the current drive I have a directory named in this way. Asking for the size of a directory leads to an exception.
4. There is no "W" drive on my environment. So here I expect another exception.

The example code is based on what you can find in the official boost filesystem tutorial. For more background information, you could have a look at the Boost filesystem version 3 home page.

No comments:

Post a Comment