Рецепт 10.12.
10.12. Чтение содержимого каталога
Требуется прочитать содержимое каталога, вероятно, для того, чтобы сделать что-то с каждым его файлом или подкаталогом.
Для получения переносимого решения воспользуйтесь классами и функциями библиотеки Boost Filesystem. Она содержит ряд удобных функций по работе с файлами, обеспечивая переносимое представление путей, итераторы каталога и различные функции по переименованию, удалению и копированию файлов и т.п. Пример 10.19 показывает, как можно использовать некоторые из этих средств.
#include <iostream>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/fstream.hpp>
using namespace boost::filesystem;
int main(int argc, char** argv) {
if (argc < 2) {
std::cerr << 'Usage: ' << argv[0] << ' [dir name]
';
return(EXIT_FAILURE);
}
path fullPath = // Создать полный, абсолютный путь
system_complete(path(argv[1], native));
if (!exists(fullPath)) {
std::cerr << 'Error: the directory ' << fullPath.string()
<< ' does not exist.
';
return(EXIT_FAILURE);
}
if (!is_directory(fullPath)) {
std::cout << fullPath.string() << ' is not a directory!
';
return(EXIT_SUCCESS);
}
directory_iterator end;
for (directory_iterator it(fullPath);
it != end; ++it) { // Просматривать в цикле каждый
// элемент каталога почти
std::cout << it->leaf(); // так же, как это делалось бы для
if (is_directory(*it)) // STL-контейнера
std::cout << ' (dir)';
std::cout << '
';
}
return(EXIT_SUCCESS);
}
Как и при создании и удалении каталогов (см. рецепты 10.10 и 10.11), не существует стандартного, переносимого способа чтения содержимого каталога. Чтобы облегчить жизнь в C++, библиотека Filesystem проекта Boost содержит ряд переносимых функций по работе с файлами и каталогами. Она также содержит много других функций; дополнительную информацию вы найдете при описании других рецептов этой главы или на веб-странице библиотеки Boost Filesystem сайта
В примере 10.19 приводится простая программа просмотра каталога (наподобие команды ls
в Unix или dir
в MS-DOS). Сначала она следующим образом формирует абсолютный путь на основе аргументов, переданных программе.
path fullPath = complete(path(argv[1], native));
Тип данных переменной, содержащей путь, называется, естественно, path
(путь). С этим типом данных работает файловая система, и он легко преобразуется в строку путем вызова path::string
. После формирования пути программа проверяет его существование (с помощью функции exists
), затем с помощью другой функции, is_directory
, проверяет, задает ли данный путь каталог. Если ответ положителен, то все хорошо и можно перейти к реальной работе по просмотру содержимого каталога.
Файловая система имеет класс с именем directory_iterator
, который использует стандартную семантику итераторов, подобную применяемой для стандартных контейнеров, чтобы можно было использовать итераторы как указатели на элементы каталога. Однако в отличие от стандартных контейнеров здесь нет функции-члена end
, представляющей элемент, следующий за последним элементом (т.е. vector<T>::end
). Вместо этого, если вы создаете итератор каталога directory_iterator
при помощи стандартного конструктора, он предоставляет конечный маркер, который вы можете использовать в операциях сравнения для определения момента завершения просмотра каталога. Поэтому используйте следующий оператор.
directory_iterator end;
Затем вы можете создать итератор для вашего пути и следующим образом сравнивать его с маркером конца.
for (directory_iterator it(fullPath); it != end; ++it) {
// выполнить любые действия с *it
std::cout << it->leaf();
}
Функция-член leaf
возвращает строку, представляющую конечный элемент пути, а не весь путь, который вы можете получить, вызывая функцию-член string
.
Если вам требуется обеспечить переносимость, но по каким-то причинам вы не можете использовать библиотеки Boost, обратите внимание на исходный код Boost. Он содержит операторы #ifdef
, которые учитывают (по большей части) отличия среды Windows и ОС, использующих интерфейс Posix, и в частности отличия в представлении путей, например буквы дисководов и имена устройств.
Рецепты 10.10 и 10.11.
10.13. Извлечение расширения файла из строки
Имеется имя файла или полный путь и требуется получить расширение файла, которое является частью имени файла, расположенной за последней точкой. Например, в именах файлов