10.10. Создание каталога
10.10. Создание каталога
Проблема
Требуется создать каталог, причем эта операция должна быть переносимой, т.е. в ней не должен использоваться специфичный для конкретной ОС программный интерфейс.
Решение
На большинстве платформ вы сможете использовать системный вызов mkdir, который входит в состав большинства компиляторов и содержится в заголовочных файлах C-функций. Он имеет разный вид в различных ОС, но тем не менее вы можете его использовать для создания нового каталога. Стандартными средствами C++ нельзя обеспечить переносимый способ создания каталога. В этом вы можете убедиться на примере 10.15.
Пример 10.15. Создание каталога
#include <iostream>
#include <direct.h>
int main(int argc, char** argv) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " [new dir name] ";
return(EXIT_FAILURE);
}
if (mkdir(argv[1]) == -1) { // Созвать каталог
std::cerr << "Error: " << strerror(errno);
return(EXIT_FAILURE);
}
}
Обсуждение
Системные вызовы по созданию каталогов слегка отличаются в различных ОС, но пусть это вас не останавливает — их все же следует использовать. В большинстве систем поддерживаются различные варианты вызова mkdir, поэтому для создания каталога достаточно просто знать, какой включать заголовочный файл и как выглядит сигнатура функции.
Пример 10.15 работает в системах Windows, но не в Unix. В Windows mkdir объявляется в <direct.h>. Эта функция принимает один параметр (имя каталога) и возвращает -1, если возникла ошибка, устанавливая в errno соответствующий номер ошибки. Вы можете получить зависящую от реализации текстовую строку ошибки, вызывая strerror или perror.
В Unix mkdir объявляется в <sys/stat.h>, и сигнатура этой функции немного отличается. Семантика ошибки такая же, как в Windows, но существует второй параметр, определяющий права доступа нового каталога. Вы должны указать права доступа, используя традиционный формат chmod (см. дополнительную информацию на man-странице chmod); например, 0777 означает, что владелец, групповой пользователь и прочие пользователи имеют право на чтение, запись и выполнение. Таким образом, вы могли бы вызвать эту функцию следующим образом.
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, char** argv) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " [new dir name] ";
return(EXIT_FAILURE);
}
if (mkdir(argv[1], 0777) == -1) { // Создать каталог
std::cerr << "Error: << strerror(errno);
return(EXIT_FAILURE);
}
}
Если вам требуется обеспечить переносимость, не следует самому писать операторы #ifdef, лучше воспользоваться библиотекой Boost Filesystem. Вы можете создать каталог, используя функцию сreate_directory, как показано в примере 10.16, который содержит короткую программу, создающую каталог.
Пример 10.16. Создание каталога средствами Boost
#include <iostream>
#include <string>
#include <cstdlib>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/fstream.hpp>
using namespace std;
using namespace boost::filesystem;
int main(int argc, char** argv) {
// Проверка параметров...
try {
path p = complete(path(argv[1], native));
create_directory(p);
} catch (exception& e) {
cerr << e.what() << endl;
}
return(EXIT_SUCCESS);
}
Функция create_directory создает каталог, имя которого вы задаете в аргументе path. Если этот каталог уже существует, выбрасывается исключение filesystem_error (которое является производным от стандартного класса исключения). Пояснения по классу path и функции complete (оба они входят в библиотеку Boost Filesystem) приводятся в обсуждении рецепта 10.7. См. рецепт 10.11, где показан пример удаления каталога и всех содержащихся в нем файлов. С другой стороны, если переносимость вас не волнует, используйте программный интерфейс файловой системы вашей ОС, который, вероятно, обладает большей гибкостью.
Смотри также
Рецепт 10.12.