36

さて、mkstempPOSIXで一時ファイルを作成するための推奨される方法です。

ただし、ファイルを開き、intファイル記述子である を返します。それから、私は FILE* のみを作成できますがstd::ofstream、C++ で好まれる は作成できません。(明らかに、AIX やその他のシステムではstd::ofstream、ファイル記述子から を作成できますが、それを試みるとコンパイラがエラーを出します。)

一時ファイル名を取得し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;
    }
}

おそらく、適切なファイル作成マスク (0600 が望ましい) を使用して umask を呼び出すようにしてください。mkstemp のマンページには、ファイル モード作成マスクは標準化されていないと書かれています。これは、mkstemp がその引数を使用するファイル名に変更するという事実を利用しています。そのため、それを開き、開いたファイルを閉じます (つまり、2 度開かないようにするため)。そのファイルに接続されたオフストリームが残ります。

于 2009-01-31T22:27:47.163 に答える
11

私はこれがうまくいくと思います:

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

編集:まあ、これは移植可能ではないかもしれません。attach を使用できず、ファイル記述子から直接 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 に答える