- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц
Шрифт:
Интервал:
Закладка:
$ ./normalizer src
/Users/tfc/src
6. Когда мы снова запускаем программу в домашнем каталоге, но даем ей запутанное относительное описание пути к файлу, в котором сначала прописывается вход в папку Desktop, потом прописывается выход из нее с помощью косвенного адреса .., затем входим в папку Documents и выходим из нее, чтобы в конечном итоге попасть в каталог src, программа отображает тот же путь файла, что и ранее!
$ ./normalizer Desktop/../Documents/../src
/Users/tfc/src
Как это работает
Этот начальный пример работы с std::filesystem мы сделали относительно коротким и прямолинейным. Мы инициализировали объект класса path на основе строки, которая содержит описание пути к файлу. Класс std::filesystem::path имеет самое первостепенное значение в тех ситуациях, когда мы используем библиотеку, связанную с файловой системой, поскольку с ним связано большинство функций и классов.
Функция filesystem::exists позволяет проверить, существует ли указанный путь файла на самом деле. До сего момента мы не можем быть в этом уверены, поскольку возможно создавать объекты класса path, которые не относятся к реальному объекту файловой системы. Функция exists всего лишь принимает экземпляр класса path и возвращает значение true в том случае, если он действительно существует. Эта функция способна сама определить, какой путь мы ей передали (абсолютный или относительный), что делает ее очень комфортной в применении.
Наконец, мы использовали функцию filesystem::canonical для каталога, чтобы вывести на экран его нормализованную форму:
path canonical(const path& p, const path& base = current_path());
Функция canonical принимает путь к файлу и в качестве необязательного второго аргумента еще один путь к файлу. Второй путь base добавляется к пути файла p в том случае, если p является относительным. После этого функция canonical пытается убрать все косвенные адреса . и .. .
Для вывода результата на экран мы использовали метод .c_str(), которому передали канонический путь к файлу. Мы сделали так потому, что перегруженный оператор << для выходных потоков берет пути к файлам в кавычки, а это не всегда желательно.
Дополнительная информация
Функция canonical генерирует исключение типа fileystem_error, если путь, который мы хотим привести к каноническому виду, не существует. Для предотвращения этого мы проверили наш путь к файлу с помощью функции exists. Но было ли достаточно данной проверки, чтобы необработанные исключения не генерировались? Нет.
Обе функции, как exists, так и canonical, способны генерировать исключения типа bad_alloc. Если бы эти исключения сгенерировались, кто-то мог бы утверждать, что программа все равно обречена. Более важная, а также гораздо более вероятная проблема возникает, когда где-то между проверкой существования файла и процессом приведения его к каноническому виду некто переименовывает или удаляет основной файл! В этом случае функция canonical сгенерирует сообщение об ошибке filesystem_error, хотя мы ранее уже убедились в том, что файл существует.
Большая часть функций файловой системы имеет еще одну перегруженную версию, которая принимает те же аргументы, а также ссылку на std::error_code:
path canonical(const path& p, const path& base = current_path());
path canonical(const path& p, error_code& ec);
path canonical(const std::filesystem::path& p,
const std::filesystem::path& base,
std::error_code& ec);
Таким образом, можно выбрать, окружать ли запросы к функциям файловой системы конструктами try-catch, или же проверять наличие ошибок вручную. Обратите внимание: это изменяет только поведение ошибок, связанных с файловой системой! Если в системе заканчивается память, то возможна генерация более сложных исключений, таких как bad_alloc, которые могут иметь или не иметь параметр ec.
Получаем канонические пути к файлам из относительных путей
В последнем примере мы уже приводили к каноническому виду/нормализовали пути файлов. Конечно же, класс filesystem::path способен не только хранить и проверять пути к файлам. Это помогает легко создавать пути к файлу из строк, а также снова разбивать их на составные части.
На данном этапе класс path позволяет абстрагироваться от деталей работы операционной системы, но в некоторых случаях все же о них следует помнить.
Мы увидим, как обращаться с путями и их композицией/декомпозицией, на примере работы с абсолютными и относительными путями.
Как это делается
В данном примере мы будем работать с абсолютными и относительными путями к файлам, чтобы увидеть сильные стороны класса path и связанных с ним вспомогательных функций.
1. Сначала включаем все необходимые заголовочные файлы и объявляем, что используем пространства имен std и filesystem:
#include <iostream>
#include <filesystem>
using namespace std;
using namespace filesystem;
2. Затем объявляем пример пути к файлу. На данный момент неважно, существует ли текстовый файл, на который он ссылается. Тем не менее есть функции, генерирующие исключения, если требуемого файла нет.
int main()
{
path p {"testdir/foobar.txt"};
3. Сейчас мы познакомимся с четырьмя разными функциями библиотеки для работы с файловой системой. Функция current_path возвращает путь, в котором в данный момент выполняется программа, — так называемый рабочий каталог. Функция absolute принимает относительный путь к файлу наподобие нашего пути p и возвращает абсолютный, однозначный путь во всей файловой системе.
Функция system_complete делает практически то же самое, что и функция absolute в Linux, MacOS или других UNIX-подобных операционных системах. В Windows мы получим абсолютный путь к файлу, только вначале будет добавлено буквенное обозначение тома диска (например, "C:"). Функция canonical опять же делает то же самое, что и функция absolute, но потом дополнительно убирает все косвенные адреса, такие как "." (сокращение для «текущий каталог») или ".." (сокращение для «один каталог вверх»). Мы рассмотрим работу с данными косвенными адресами в следующих шагах.
cout << "current_path : " << current_path()
<< "nabsolute_path : " << absolute(p)
<< "nsystem_complete : " << system_complete(p)
<< "ncanonical(p) : " << canonical(p)
<< 'n';
4. Еще одна приятная особенность класса path заключается в том, что он перегружает оператор /. Таким образом, можно сцеплять имена папок и имена файлов с помощью данного оператора и составлять из них пути файлов. Попробуем это и отобразим составной путь:
cout