36

好的,mkstemp这是在 POSIX 中创建临时文件的首选方式。

但它会打开文件并返回一个int,这是一个文件描述符。从那我只能创建一个 FILE*,但不能创建一个std::ofstream,我更喜欢在 C++ 中。std::ofstream(显然,在 AIX 和其他一些系统上,您可以从文件描述符创建一个,但是当我尝试这样做时,我的编译器会报错。)

我知道我可以得到一个临时文件名,tmpnam然后用它打开我自己的 ofstream,但这显然是不安全的,因为竞争条件,并导致编译器警告(Linux 上的 g++ v3.4.):

warning: the use of `tmpnam' is dangerous, better use `mkstemp'

那么,是否有任何可移植的方式来创建std::ofstream临时文件?

4

4 回答 4

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。

于 2009-01-31T22:27:47.163 回答
11

我认为这应该有效:

    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已经为您创建了文件,因此竞争条件在这里应该不是问题。

于 2009-01-31T21:50:47.907 回答
2

也许这会起作用:

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

我没试过,你可以看看。

于 2011-08-18T15:44:26.880 回答
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。也感谢其他对我有帮助的回复。

于 2017-10-31T04:17:22.580 回答