Как создать std:: ofstream для временного файла?
хорошо, mkstemp
является предпочтительным способом создания временного файла в POSIX.
но он открывает файл и возвращает int
, который является файловым дескриптором. Из этого я могу создать только файл*, но не std::ofstream
, который я бы предпочел в C++. (По-видимому, в AIX и некоторых других системах вы можете создать std::ofstream
из файлового дескриптора, но мой компилятор жалуется, когда я пытаюсь это сделать.)
Я знаю, что могу получить имя временного файла с tmpnam
а затем открыть свой собственный ofstream с ним, но это, по-видимому, небезопасно из-за условий гонки и приводит к предупреждению компилятора (g++ v3.4. на Linux):
warning: the use of `tmpnam' is dangerous, better use `mkstemp'
Итак, есть ли какой-либо портативный способ создать std::ofstream
во временный файл?
4 ответов
Я думаю, что это должно работать:
char *tmpname = strdup("/tmp/tmpfileXXXXXX");
ofstream f;
int fd = mkstemp(tmpname);
f.attach(fd);
EDIT: Ну, это не может быть портативным. Если вы не можете использовать attach и не можете создать ofstream непосредственно из файлового дескриптора, то вам нужно сделать следующее:
char *tmpname = strdup("/tmp/tmpfileXXXXXX");
mkstemp(tmpname);
ofstream f(tmpname);
As mkstemp уже создает файл для вас, условия конкуренции не должно быть проблемой здесь.
Я сделал эту функцию:
#include <stdlib.h>
#include <fstream>
#include <iostream>
#include <vector>
std::string open_temp(std::string path, std::ofstream& f) {
path += "/XXXXXX";
std::vector<char> dst_path(path.begin(), path.end());
dst_path.push_back('');
int fd = mkstemp(&dst_path[0]);
if(fd != -1) {
path.assign(dst_path.begin(), dst_path.end() - 1);
f.open(path.c_str(),
std::ios_base::trunc | std::ios_base::out);
close(fd);
}
return path;
}
int main() {
std::ofstream logfile;
open_temp("/tmp", logfile);
if(logfile.is_open()) {
logfile << "hello, dude" << std::endl;
}
}
вы, вероятно, должны обязательно вызвать umask с правильной маской создания файла (я бы предпочел 0600)- manpage для mkstemp говорит, что маска создания режима файла не стандартизирована. Он использует тот факт, что mkstemp изменяет свой аргумент на имя файла, которое он использует. Итак, мы открываем его и закрываем файл, который он открыл (так, чтобы он не открывался дважды), оставаясь с ofstream, который подключен к этому файлу.
возможно, это сработает:
char tmpname[256];
ofstream f;
sprintf (tmpname, "/tmp/tmpfileXXXXXX");
int fd = mkstemp(tmpname);
ofstream f(tmpname);
Я не пробовал, но можно проверить.
char tempFileName[20]; // name only valid till next invocation of tempFileOpen
ofstream tempFile;
void tempFileOpen()
{
strcpy(tempFileName, "/tmp/XXXXXX");
mkstemp(tempFileName);
tempFile.open(tempFileName);
}
этот код работает для меня с GCC / libstdc++6 4.8.4 и Clang 3.9. Благодаря другим ответам, которые были полезны для меня.