Работа с файловой системой без WinAPI/Linux API
std::filesystem присутствует только в стандарте C++17, потому надо выставить именно этот стандарт в настройках компилятора. Если же вы по какой-то причине не можете или не хотите использовать этот стандарт, а только более старые, то вместо
#include
<filesystem>
вам потребуется
#include <experimental/filesystem>
Однако, во втором случае пространство имён filesystem будет доступно только в пространстве имён std::experimental, а я буду ориентироваться на первый случай, поэтому все, кто пользуется каким-нибудь C++14, то вставьте в свой код это:
#ifdef _EXPERIMENTAL_FILESYSTEM_ namespace std { using namespace experimental; } #endif // _EXPERIMENTAL_FILESYSTEM_
Зачем же нам нужен std::filesystem, если в Windows есть WinAPI штуки для работы с путями, как и в линуксе? Потому что так проще и код получается менее платформозависимым.
Кодировка
Windows любит wchar_t, UNIX же, напротив, обычный char. Из-за этой особенности мы для Windows будем использовать вывод в консоль через std::wcout, а в UNIX через std::cout. Мне привычнее второй вариант, но вы так же без проблем можете использовать и первый за исключением некоторых нюансов.
Класс std::filesystem::path
Итак, когда мы настроили кодировку, то можем рассмотреть класс, который мы в последствии будем часто использовать.
Создаётся объект std::filesystem::path вот так (примеры):
std::filesystem::path path1 = std::filesystem::current_path(); std::filesystem::path path2 = "New folder 1"; //так же принимает строки типа std::string и std::wstring std::filesystem::path path3 = path2 / "Sub folder"; //"New folder/Sub folder", такой интересный синтаксис std::filesystem::path path4 = path3.parent_path(); //path4 такой же, как и path2
Но это относительный путь, можно получить и абсолютный:
std::filesystem::path Absolute = std::filesystem::absolute(path1); //path содержит абсолютный путь до текущей директории
Есть и не менее интересные методы этого класса, но у нас и так много работы впереди, их можно рассмотреть здесь.
Работа с директориями/файлами
С прошлого раздела у нас осталась директория "New folder 1/Sub folder/", предлагаю поместить руками туда файл text.txt, теперь наш файл имеет такой относительный путь: "New folder 1/Sub folder/text.txt"
А точно ли? Можем проверить при помощи следующей функции:
bool std::filesystem::exists(const std::filesystem::path& _Target);
Пример:
if (!std::filesystem::exists("New folder 1/Sub folder/text.txt") std::cerr << "File not found!" << std::endl;
Но мы же положили туда файл, потому сообщения об ошибке не должно быть (если будет, то прошу ко мне в личку скинуть код).
Теперь научимся создавать директории, вот код:
std::filesystem::path path("New folder 1"); std::filesystem::create_directory("New folder 2"); std::filesystem::create_directory(path / "Sub folder 2");
Здесь мы создаём папку "New folder 2" и "Sub folder 2" внутри "New folder 1", вот как это выглядит:
Мне больше не нужна директория "New folder 2", хочу от неё избавиться, но в ней есть другая директория, то есть нужен рекурсивный обход? Верно, но здесь это реализовано:
std::filesystem::remove_all("New folder 2");
А если рекурсивный обход не нужен или я хочу удалить один лишь файл?
std::filesystem::remove("New folder 1/Sub folder 1/text.txt");
И да, я указываю строку, хотя функции принимают путь. Дело в том, что так можно.
Так же, по мелочи, мы можем переименовать файл или папку, делается это следующим образом:
std::filesystem::rename("New folder 1/Sub folder/text.txt", "document.txt");
Правда, вы не найдёте свой файл больше в Sub folder, потому что забыли указать во втором аргументе, что он там должен остаться, то есть мы его ещё и переместили, но исправим:
std::filesystem::rename("New folder 1/Sub folder/text.txt", "New folder 1/Sub folder/document.txt");
Можно даже скопировать, скопировать файл или ссылку, я просто оставлю прототипы функций здесь:
void std::filesystem::copy(const std::filesystem::path& _From, const std::filesystem::path& _To); bool std::filesystem::copy_file(const std::filesystem::path& _From, const std::filesystem::path& _To); void std::filesystem:copy_symlink(const std::filesystem:path& _Symlink, const std::filesystem:path& _New_symlink);
Можно обрезать/дополнять файлы, если дополняем, то прибавленный размер заполняется нулями, вот пример использования:
std::filesystem::resize_file(path / "Sub folder" / "document.txt", 128);
Напомню, что файл был до этого пустой.
Метаданные
Размер файлы вычисляется функцией, пример которой ниже:
std::filesystem::file_size("New folder 1/Sub folder/documents.txt");
А вот пример использования:
if (std::filesystem::file_size("New folder 1/Sub folder/documents.txt" != 1024) std::filesystem::resize_file("New folder 1/Sub folder/documents.txt", 1024);
Узнать время последней записи:
std::filesystem::last_write_time("New folder 1/Sub folder/document.txt");
Возвращает объект класса std::filesystem::file_time_type.
Изменение прав доступа осуществляется функцией std::filesystem::permissions, которая имеет три версии, однако покажу всего одну и ту на примере:
std::filesystem::permissions("New folder 1/Sub folder/document.txt", std::filesystem::perms::all);
std::filesystem::perms — перечисление:
Статья получилась короче, чем я планировал из-за того, что писал довольно долго, а выложить нужно сегодня.
Желающим почитать:
https://en.cppreference.com/w/cpp/filesystem
https://www.codingame.com/playgrounds/5659/c17-filesystem
https://docs.microsoft.com/en-us/cpp/standard-library/filesystem?view=vs-2019