Программный код, обеспечивающий просмотр содержимого каталога, требует некоторых пояснений, и это является темой рецепта 10.12.
Библиотека Boost Filesystem достаточно удобна, однако следует помнить, что формально она не является стандартом, и поэтому нет гарантии, что она будет работать в любой среде. Если вы посмотрите на исходный код библиотеки Boost Filesystem, вы увидите, что фактически она компилирует системные вызовы, специфичные для целевой платформы. Если вас не волнует переносимость, используйте программный интерфейс файловой системы вашей ОС, который, вполне вероятно, обладает большей гибкостью.
Рецепт 10.12.
10.12. Чтение содержимого каталога
Требуется прочитать содержимое каталога, вероятно, для того, чтобы сделать что-то с каждым его файлом или подкаталогом.
Для получения переносимого решения воспользуйтесь классами и функциями библиотеки Boost Filesystem. Она содержит ряд удобных функций по работе с файлами, обеспечивая переносимое представление путей, итераторы каталога и различные функции по переименованию, удалению и копированию файлов и т.п. Пример 10.19 показывает, как можно использовать некоторые из этих средств.
#include
#include
#include
using namespace boost::filesystem;
int main(int argc, char** argv) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " [dir name]\n";
return(EXIT_FAILURE);
}
path fullPath = // Создать полный, абсолютный путь
system_complete(path(argv[1], native));
if (!exists(fullPath)) {
std::cerr << "Error: the directory " << fullPath.string()
<< " does not exist.\n";
return(EXIT_FAILURE);
}
if (!is_directory(fullPath)) {
std::cout << fullPath.string() << " is not a directory!\n";
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 << '\n';
}
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
). Вместо этого, если вы создаете итератор каталога directory_iterator
при помощи стандартного конструктора, он предоставляет конечный маркер, который вы можете использовать в операциях сравнения для определения момента завершения просмотра каталога. Поэтому используйте следующий оператор.
directory_iterator end;