The header <filesystem> is where all the goodies concerning files and directories themselves, and not their contents, can be found. The main type is std::filesystem::path; it's an object that stores a file system path in a format that the operating system can handle. Here's a basic path object created from a string literal:
#include <iostream>
#include <filesystem>
int main()
{
std::filesystem::path p{"data.txt"};
std::cout << p.string() << '\n';
return 0;
}
The object p is a std::filesystem::path. The constructor accepts the characters data.txt and stores them as a path. The member function string will return a std::string that contains the exact same character sequence, but in the platform native format.
Thus, the insertion prints data.txt.
Passing an empty string to the constructor is still a perfectly valid operation and represents the empty path.
Once you have a path object, you can investigate it. The free function std::filesystem::exists will tell you whether the path refers to something that currently exists in the file system.
#include <iostream>
#include <filesystem>
int main()
{
std::filesystem::path p{"data.txt"};
// Check this condition before entering the block
if (std::filesystem::exists(p))
std::cout << "exists\n";
else
std::cout << "does not exist\n";
return 0;
}
The call to std::filesystem::exists(p) probes into p and checks the operating system to see whether there's something with the indicated name. If a file or a directory bearing that name exists, the function returns true and the first message is printed. Otherwise, it returns false and the second message is printed.
This check won't actually open any files; it'll just query the operating system.
A path that exists can be examined in other ways, for instance, to see if it names an ordinary file or a directory:
#include <iostream>
#include <filesystem>
int main()
{
std::filesystem::path p{"data.txt"};
if (std::filesystem::is_regular_file(p))
std::cout << "regular file\n";
else if (std::filesystem::is_directory(p))
std::cout << "directory\n";
else
std::cout << "other\n";
return 0;
}
If data.txt is an ordinary file, the first if condition passes. If it's a directory, the else if branch is taken. Anything else falls into the last else block.
For these functions, like many others in <filesystem>, paths are passed by value, and their Boolean return value can be directly used in conditions.
Path building using the overloaded division operator: Paths can be built by combining smaller pieces.
#include <iostream>
#include <filesystem>
int main()
{
std::filesystem::path dir{"output"};
std::filesystem::path file{"log.txt"};
std::filesystem::path full = dir / file;
std::cout << full.string() << '\n';
return 0;
}
The two path objects dir and file are initialized with string literals. Expression dir / file creates a new path representing the name log.txt inside the directory output. The platform's preferred directory separator, e.g., / or \, is chosen automatically, so you don’t have to worry about platform specific separators.
Creating a directory: You can create a directory that doesn't exist yet with the function std::filesystem::create_directory:
#include <iostream>
#include <filesystem>
int main()
{
std::filesystem::path dir{"output"};
// Create the directory at this path
if (std::filesystem::create_directory(dir))
std::cout << "created\n";
else
std::cout << "not created\n";
return 0;
}
create_directory attempts to make a directory using the name given by path. If the directory did not already exist and creation was successful, it returns true. If the directory already existed, or the system denied the request, it returns false.
Even if the directory already exists, create_directory does not throw an exception; it simply returns false.
Removing a file or directory: To remove a file or an empty directory:
#include <iostream>
#include <filesystem>
int main()
{
std::filesystem::path p{"data.txt"};
// Remove this filesystem entry
if (std::filesystem::remove(p))
std::cout << "removed\n";
else
std::cout << "not removed\n";
return 0;
}
std::filesystem::remove takes a path, and, if the named object is a file or an empty directory, removes it. It returns true if it was successful, and false if the object does not exist or cannot be removed. In either case, the return value can be used to check for success or failure.
Thus, the type std::filesystem::path, together with the suite of functions acting on it in <filesystem>, provide a homogeneous, cross platform mechanism to name, examine, create, and remove file system entities.
0 comments
No comments yet. Be the first.