2009-01-31 88 views
31

好的,mkstemp是在POSIX中创建临时文件的首选方法。如何创建std :: ofstream到临时文件?

但它打开文件并返回一个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到一个临时任何便携式方式文件?

回答

10

我认为这应该工作:

char *tmpname = strdup("/tmp/tmpfileXXXXXX"); 
    ofstream f; 
    int fd = mkstemp(tmpname); 
    f.attach(fd); 

编辑:嗯,这可能无法移植。如果您无法使用附加并不能直接从文件描述符创建一个ofstream的,那么你必须这样做:

char *tmpname = strdup("/tmp/tmpfileXXXXXX"); 
mkstemp(tmpname); 
ofstream f(tmpname); 

由于mkstemp为您创建的文件,竞争条件不应该这里有一个问题。

+0

这不能在Linux上用我的g ++ v3.4.4编译。显然只有一些平台具有这种功能。 – Frank 2009-01-31 21:54:08

+0

谢谢!对于你的第二种方法(使用mkstemp,然后是ofstream):在I/O方面它仍然有效吗?这将访问文件系统两次,对吧?我们的文件系统非常慢,我担心会给它带来不必要的负担。 – Frank 2009-01-31 22:28:55

16

我做这个功能:

#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('\0'); 

    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) - 为mkstemp手册页说,文件模式创建掩码不规范。它使用mkstemp将其参数修改为它使用的文件名的事实。所以,我们打开它并关闭它打开的文件(所以,不要打开它两次),剩下一个连接到该文件的ofstream。

2

也许这将工作:

char tmpname[256]; 
ofstream f; 
sprintf (tmpname, "/tmp/tmpfileXXXXXX"); 
int fd = mkstemp(tmpname); 
ofstream f(tmpname); 

我还没有尝试过,但你可以检查。

0
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。感谢其他回复以及对我有帮助的回复。