Чтение онлайн

ЖАНРЫ

C++. Сборник рецептов

Когсуэлл Джефф

Шрифт:

 fgets(buf, 255, pf); // Считать оттуда строку

 fclose(pf);

 std:cout << buf << '\n';

}

Обсуждение

Создать временный файл можно двумя способами; в примере 10.13 показан один из них. Функция

tmpfile
объявляется в
<cstdio>
; она не имеет параметров и возвращает
FILE*
при успешном завершении и
NULL
в противном случае.
FILE*
— это тот же самый тип, который может использоваться функциями С, обеспечивающими ввод-вывод;
fread
,
fwrite
,
fgets
,
puts
и т.д.
tmpfile
открывает временный файл в режиме «wb+» — это означает, что вы можете записывать в него или считывать его в двоичном режиме (т.е. при чтении символы никак специально не интерпретируются) После нормального завершения работы программы временный файл, созданный функцией
tmpfile
, автоматически удаляется.

Такой подход может как подойти, так и не подойти для вас — все зависит от того, что вы хотите делать. Заметив, что

tmpfile
не предоставляет имени файла, вы спросите, как можно передать его другой программе? В этом случае никак; вам потребуется вместо этой функции использовать аналогичную с именем
tmpnam
.

tmpnam
на самом деле не создает временный файл, она просто создает уникальное имя файла, которое вы можете использовать при открытии файла,
tmpnam
принимает единственный параметр типа
char*
и возвращает значение типа
char*
. Вы можете передать указатель на буфер символов
char
(он должен быть, по крайней мере, не меньше значения макропеременной
L_tmpnam
, также определенной в
<cstdio>
), куда
tmpnam
скопирует имя временного файла и возвратит указатель на тот же самый буфер. Если вы передадите
NULL
,
tmpfile
возвратит указатель на статический буфер, содержащий это имя файла, что означает его перезапись последующими вызовами
tmpnam
. (См. пример 10.14.)

Пример 10.14. Создание имени временного файла

#include <iostream>

#include <fstream>

#include <cstdio>

#include <string>

int main {

 char* pFileName = NULL;

 pFileName = tmpnam(NULL);

 // Здесь другая программа может получить то же самое имя временного

 // файла.

 if (!pFileName) {

std::cerr << "Couldn't create temp file name.\n";

return(EXIT_FAILURE);

 }

 std::cout << "The temp file name is: " << pFileName << '\n';

 std::ofstream of(pFileName);

 if (of) {

of << "Here is some temp data.";

of.close;

 }

 std::ifstream ifs(pFileName);

 std::string s;

 if (ifs) {

ifs >> s;

std::cout << "Just read in \"" << s << "\"\n";

ifs.close;

 }

}

Однако одну важную особенность необходимо знать о функции

tmpnam
. Может возникнуть условие состязания, когда несколько процессов могут генерировать одинаковое имя файла, если один процесс вызывает
tmpname
, а другой вызывает
tmpname
до того, как первый процесс откроет этот файл. Это плохо по двум причинам. Во-первых, написанная злоумышленником программа может делать это для перехвата данных временного файла, и, во-вторых, ни о чем не подозревающая программа может получить то же самое имя файла и просто испортить или удалить данные.

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]\n";

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]\n";

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>

Поделиться с друзьями: