}
return(EXIT_SUCCESS);
}
В этой небольшой программе все же имеется несколько ключевых вопросов, которые необходимо пояснить, поскольку другие рецепты данной главы используют библиотеку Boost Filesystem. Во первых, центральным компонентом библиотеки Boost Filesystem является класс path
, описывающий независимым от ОС способом путь к файлу или каталогу. Вы можете создать path
, используя как переносимый тип строки, так и специфичный для конкретной ОС. В примере 10.10 я создаю путь path
из аргументов программы (этот путь я затем передаю функции complete
, которую мы вскоре рассмотрим).
path src = complete(path(argv[1], native));
Первый аргумент — это текстовая строка, представляющая путь, например «tmp foo.txt
», а второй аргумент — имя функции, которая принимает аргумент типа string
и возвращает значение типа Boolean
, которое показывает, удовлетворяет или нет путь определенным правилам. Функция native
говорит о том, что проверяется родной формат ОС. Я его использовал в примере 10.10, потому что аргументы берутся из командной строки, где они, вероятно, вводятся человеком, который, по-видимому, использует родной формат ОС при задании имен файлов. Существует несколько функций, предназначенных для проверки имен файлов и каталогов и названия которых не требует пояснений: portable_posix_name
, windows_name
, portable_name
, portable_directory_name
, portable_file_name
и no_check
. Особенности работы этих функций вы найдете в документации.
Функция complete
формирует абсолютный путь, используя текущий рабочий каталог и переданный ее относительный путь. Так, я могу следующим образом создать абсолютный путь к исходному файлу.
path src = complete(path('tmp\foo.txt', native));
В том случае, если первый аргумент уже имеет абсолютное имя файла, функция complete
выдает заданное значение и не будет пытаться его присоединить к текущему рабочему каталогу. Другими словами, в следующем операторе, выполняемом при текущем каталоге «c:myprograms
», последний будет проигнорирован, потому что уже задан полный путь.
path src = complete(path('c:\windows\garbage.txt', native));
Многие функции из библиотеки Boost Filesystem будут выбрасывать исключения, если не удовлетворяется некоторое предусловие. Это подробно описано в документации, но хорошим примером является сама функция copy_file
. Файл должен существовать перед копированием, поэтому если исходного файла нет, операция не будет завершена успешно и copy_file
выбросит исключение. Перехватите исключение, как я это сделал в примере 10.10, и вы получите сообщение об ошибке, объясняющее, что произошло.
10.8. Удаление или переименование файла
Требуется удалить или переименовать файл и сделать эту операцию переносимой, те. без использования специфичного для конкретной ОС программного интерфейса.
Это сделают стандартные C-функции remove
и rename
, определенные в <cstdio>
. Пример 10.11 кратко демонстрирует, как это делается.
#include <iostream>
include <cstdio>
#include <cerrno>
using namespace std;
int main(int argc, char** argv) {
if (argc != 2) {
cerr << 'You must supply a file name to remove.' << endl;
return(EXIT_FAILURE);
}
if (remove(argv[1]) == -1) { // remove() возвращает при ошибке -1
cerr << 'Error: ' << strerror(errno) << endl;
return(EXIT_FAILURE);
} else {
cout << 'File '' << argv[1] << '' removed.' << endl;
}
}
Эти системные вызовы легко использовать: просто вызовите любую из двух функций, передав ей имя файла, который требуется удалить или переименовать. Если что-то не получится, будет возвращено ненулевое значение, и errno
будет иметь номер соответствующей ошибки. Вы можете использовать strerror
или perror
(обе функции определены в <cstdio>
) для вывода на печать сообщения об ошибке, зависящего от реализации.
Для переименования файла следует поменять в примере 10.11 вызов функции remove
следующим программным кодом.
if (rename(argv[1], argv[2])) {
cerr << 'Error: ' << strerror(errno) << endl;
return(EXIT_FAILURE);
}
Библиотека Boost Filesystem также предоставляет средства для удаления и переименования файла. В примере 10.12 показана короткая программа по удалению файла (или каталога, однако см. обсуждение, приводимое после этою примера).
#include <iostream>
#include <string>
#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));
remove(p);
} catch (exception& e) {
cerr << e.what() << endl;