Создать временный файл можно двумя способами; в примере 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.
Системные вызовы по созданию каталогов слегка отличаются в различных ОС, но пусть это вас не останавливает — их все же следует использовать. В большинстве систем поддерживаются различные варианты вызова
mkdir
, поэтому для создания каталога достаточно просто знать, какой включать заголовочный файл и как выглядит сигнатура функции.
Пример 10.15 работает в системах Windows, но не в Unix. В Windows
mkdir
объявляется в
<direct.h>
. Эта функция принимает один параметр (имя каталога) и возвращает -1, если возникла ошибка, устанавливая в errno соответствующий номер ошибки. Вы можете получить зависящую от реализации текстовую строку ошибки, вызывая strerror или perror.
В Unix
mkdir
объявляется в
<sys/stat.h>
, и сигнатура этой функции немного отличается. Семантика ошибки такая же, как в Windows, но существует второй параметр, определяющий права доступа нового каталога. Вы должны указать права доступа, используя традиционный формат
chmod
(см. дополнительную информацию на man-странице
chmod
); например, 0777 означает, что владелец, групповой пользователь и прочие пользователи имеют право на чтение, запись и выполнение. Таким образом, вы могли бы вызвать эту функцию следующим образом.