The member functions presented with boost::filesystem::path
simply process strings. They access individual components of a path, append paths to one another, and so on.
In order to work with physical files and directories on the hard drive, several free-standing functions are provided. They expect one or more parameters of type boost::filesystem::path
and call operating system functions internally.
Prior to introducing the various functions, it is important to understand what happens in case of an error. All of the functions call operating system functions that may fail. Therefore, Boost.Filesystem provides two variants of the functions that behave differently in case of an error:
The first variant throws an exception of type boost::filesystem::filesystem_error
. This class is derived from boost::system::system_error
and thus fits into the Boost.System framework.
The second variant expects an object of type boost::system::error_code
as an additional parameter. This object is passed by reference and can be examined after the function call. In case of a failure, the object stores the corresponding error code.
boost::system::system_error
and boost::system::error_code
are presented in Chapter 55. In addition to the inherited interface from boost::system::system_error
, boost::filesystem::filesystem_error
provides two member functions called path1()
and path2()
, both of which return an object of type boost::filesystem::path
. Since there are functions that expect two parameters of type boost::filesystem::path
, these two member functions provide an easy way to retrieve the corresponding paths in case of a failure.
boost::filesystem::status()
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
path p{"C:\\"};
try
{
file_status s = status(p);
std::cout << std::boolalpha << is_directory(s) << '\n';
}
catch (filesystem_error &e)
{
std::cerr << e.what() << '\n';
}
}
Example 35.10 introduces boost::filesystem::status()
, which queries the status of a file or directory. This function returns an object of type boost::filesystem::file_status
, which can be passed to additional helper functions for evaluation. For example, boost::filesystem::is_directory()
returns true
if the status for a directory was queried. Besides boost::filesystem::is_directory()
, other functions are available, including boost::filesystem::is_regular_file()
, boost::filesystem::is_symlink()
, and boost::filesystem::exists()
, all of which return a value of type bool
.
The function boost::filesystem::symlink_status()
queries the status of a symbolic link. With boost::filesystem::status()
the status of the file referred to by the symbolic link is queried. On Windows, symbolic links are identified by the file extension lnk
.
boost::filesystem::file_size()
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
path p{"C:\\Windows\\win.ini"};
boost::system::error_code ec;
boost::uintmax_t filesize = file_size(p, ec);
if (!ec)
std::cout << filesize << '\n';
else
std::cout << ec << '\n';
}
A different category of functions makes it possible to query attributes. The function boost::filesystem::file_size()
returns the size of a file in bytes. The return value is of type boost::uintmax_t
, which is a type definition for unsigned long long
. The type is provided by Boost.Integer.
Example 35.11 uses an object of type boost::system::error_code
, which needs to be evaluated explicitly to determine whether the call to boost::filesystem::file_size()
was successful.
boost::filesystem::last_write_time()
#include <boost/filesystem.hpp>
#include <iostream>
#include <ctime>
using namespace boost::filesystem;
int main()
{
path p{"C:\\Windows\\win.ini"};
try
{
std::time_t t = last_write_time(p);
std::cout << std::ctime(&t) << '\n';
}
catch (filesystem_error &e)
{
std::cerr << e.what() << '\n';
}
}
To determine the time a file was modified last, boost::filesystem::last_write_time()
can be used (see Example 35.12).
boost::filesystem::space()
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
path p{"C:\\"};
try
{
space_info s = space(p);
std::cout << s.capacity << '\n';
std::cout << s.free << '\n';
std::cout << s.available << '\n';
}
catch (filesystem_error &e)
{
std::cerr << e.what() << '\n';
}
}
boost::filesystem::space()
retrieves the total and remaining disk space (see Example 35.13). It returns an object of type boost::filesystem::space_info
, which provides three public member variables: capacity, free, and available, all of type boost::uintmax_t
. The disk space is in bytes.
While the functions presented so far leave files and directories untouched, there are several functions that can be used to create, rename, or delete files and directories.
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
path p{"C:\\Test"};
try
{
if (create_directory(p))
{
rename(p, "C:\\Test2");
boost::filesystem::remove("C:\\Test2");
}
}
catch (filesystem_error &e)
{
std::cerr << e.what() << '\n';
}
}
Example 35.14 should be self-explanatory. Looking closely, one can see that it’s not always an object of type boost::filesystem::path
that is passed to functions, but rather a simple string. This is possible because boost::filesystem::path
provides a non-explicit constructor that will convert strings to objects of type boost::filesystem::path
. This makes it easy to use Boost.Filesystem since it’s not required to create paths explicitly.
In Example 35.14, boost::filesystem::remove()
is explicitly called using its namespace. Otherwise, Visual C++ 2013 would confuse the function with remove()
from the header file stdio.h
.
Additional functions such as create_symlink()
to create symbolic links or copy_file()
and copy_directory()
to copy files and directories are available as well.
boost::filesystem::absolute()
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
try
{
std::cout << absolute("photo.jpg") << '\n';
}
catch (filesystem_error &e)
{
std::cerr << e.what() << '\n';
}
}
Example 35.15 presents a function that creates an absolute path based on a file name or section of a path. The path displayed depends on which directory the program is started in. For example, if the program was started in C:\
, the output would be "C:\photo.jpg"
.
To retrieve an absolute path relative to a different directory, a second parameter can be passed to boost::filesystem::absolute()
.
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
try
{
std::cout << absolute("photo.jpg", "D:\\") << '\n';
}
catch (filesystem_error &e)
{
std::cerr << e.what() << '\n';
}
}
Example 35.16 displays "D:\photo.jpg"
.
The last example in this section, Example 35.17, introduces a useful helper function to retrieve the current working directory.
boost::filesystem::current_path()
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
try
{
std::cout << current_path() << '\n';
current_path("C:\\");
std::cout << current_path() << '\n';
}
catch (filesystem_error &e)
{
std::cerr << e.what() << '\n';
}
}
Example 35.17 calls boost::filesystem::current_path()
multiple times. If the function is called without parameters, the current working directory is returned. If an object of type boost::filesystem::path
is passed, the current working directory is set.