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.