Weekly C++ 6 – Filesystem Library

Hello everybody, after a break (hopefully not very long), we are together again with another weekly C++ post. In this post, we are going to explore a very anticipated standard library feature which is filesystem library (Well Java and .Net have this feature for a very long time why not us).
This library is based on boost::filesystem which is available for a long time (since 2003) so if you would like to use that path well you can (I also added a link for comparison of boost and std version comparison for curious;). The most obvious benefit of this library as you may guess is to write multiplatform and standard code. In this post, we will go over most obvious features of library, and illustrate the possible usage via examples and provide references for more details. I may provide some example usage of this library in following posts.

Overview:

As pointed out in Stackoverflow Post, there are some papers making changes to current filesystem library which are listed as follow:

  • P0219R1, adding relative paths support,
  • P0317R1, adding caching to directory_entry,
  • P0492R2, a lengthy list of fixes and changes in response to national body comments,
  • P0430R2, support for certain non-POSIX systems,
  • P0218R1, final paper.

In fact, the latest status can be observed via in the LWG issue list. You can check out other capabilities’ status.

You can also check out the complete standard in which filesystems are explained under section 30.10 (input/output library). Beware that, this document is little bit large:)

Well as I mentioned above, library is based on boost::filesystem and some of its components are optional which means that you may not use every feature on every platform or compiler (i.e. symbolic links are not supported in FAT-32). You also need to take some platform specific issues into consideration such as:

  • File name case sensivity. For instance, “file.txt” and “File.txt” and “file.TXT” might refer to the same file in Windows OS or three different files POSIX-based OS like Linux,
  • Absolute/relative path approach. On some systems “/bin” is an absolute path in POSIX-based OS es, while on others it is not Windows OS.

The most important concepts of this library is path. It is a label which possibly represents a location of a file within system which may not be of course a file. It may represent folders, hard links, symbolic links or regular files (standard files). You can check the web site of filesystem library for all enumerations. Paths on the other hand can be absolute or relative. Some platforms may have generic/native path formats. On Windows OS, the generic format “/tmp/test.txt” is a valid native format besides “\tmp\test.txt“, which is also supported (thus, “/tmp/test.txt” and “\tmp\test.txt” are two native versions of the same path). Of course, library provides APIs to convert paths between the native and generic format.

The generic path format can be summarized as:
            [rootname] [rootdir] [relativepath]
where:

  • The optional root name is implementation specific (e.g., it can be “//host” on POSIX systems and “C:” on Windows systems),
  • The optional root directory is a directory separator,
  • The relative path is a sequence of file names separated by directory separators.

Filesystem library is a very large library which is not in fact possible to cover each detail in this post so I will try to focus on most important and practical features through code examples. If you want to learn more details, I highly recommend Nicolai M. Josuttis and other C++ 17 books that I give in references which cover filesystems in a more detailed fashion.

The filesystem library is provided through <filesystem> and filesystem namespace. There are both classes and freestanding functions in library. By default, library handles errors (which may occur more than other libraries because of its nature) through exceptions (filesystem_error exception), however you can also get error code (std::error_code) if you pass an additional parameter to corresponding API (in addition to return value).

The namespace and include header may change according to you compiler, please check last section and you compiler support page for details.

Let’s start to look at file system library with a simple example:

Here, you can see that basic folder operations can easily be performed by these APIs. So what can we do else with this library? Well briefly:

  • Create/inspect paths,
  • Path modifications and comparisons,
  • Path name conversion between native and generic formats,
  • Iterating over directories/files,
  • Working with file attributes/flags, status and permissions,
  • File system modifications (create/delete/copy/move files),
  • For much more, check out https://en.cppreference.com/w/cpp/filesystem.

Path Objects:

Let us start with path object which probably used most. Following code example summarize mosst common usage of path object.

Disk Space Info:

Another useful object is std::filesystem::space_info which can be used to obtain total size of the filesystem, free space and available space on the filesystem as follow:

Permissions:

You can also access and play with permission attributes of files which is illustrated in following example. “std::filesystem::perms” which is BitmaskType is used with some predefined bit masks which can be found at (https://en.cppreference.com/w/cpp/filesystem/perms). Follwing sample code shows how you can read and update these permissions.

Last Modified Time:

You can also use filesystem library with other libraries such as std::chrono to display last modified time of given file. An example usage is illustrated below:

Compiler/Library support:

By the way, the compiler support of this feature can be checked with other C++ features via https://en.cppreference.com/w/cpp/compiler_support.
Depending on the version of your compiler you might need to use std::experimental::filesystem namespace.

GCC: “-lstdc++fs” should be specified when you want filesystem. “<experimental/filesystem> header should be included.
Clang should be ready with Clang 5.0
https://libcxx.llvm.org/cxx1z_status.html
Visual Studio: In case of Visual Studio, you need to include <filesystem> and std::experimental::filesystem namespace should be used.

References

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.