如何在C++中创建临时目录?

发布于 2024-09-12 11:18:53 字数 88 浏览 12 评论 0原文

我正在用 C++ 编写一个函数来创建一个临时目录。这样的功能应该尽可能地具有可移植性,例如它应该在linux、mac和win32环境下工作。我该如何实现这一目标?

I'm writing a function in C++ which creates a temporary directory. Such function should be as most portable as possible, e.g. it should work under linux, mac and win32 environments. How do I achieve that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

天暗了我发光 2024-09-19 11:18:53

Boost 文件系统库的版本 3 提供了函数 unique_path() 来生成适合创建临时文件或目录的路径名。

using namespace boost::filesystem;

path ph = temp_directory_path() / unique_path();
create_directories(ph);

Version 3 of Boost Filesystem Library provides function unique_path() for generating a path name suitable for creating a temporary file or directory.

using namespace boost::filesystem;

path ph = temp_directory_path() / unique_path();
create_directories(ph);
好倦 2024-09-19 11:18:53

C++17 std::filesystem::temp_directory_path + 随机数生成

这是一个可能可靠的纯 C++17 解决方案:没有 Boost 或其他外部库,并且没有 mkdtemp 这是 POSIX

我们只是循环随机数,直到能够创建一个以前不存在的目录 < code>std::filesystem::temp_directory_path(Ubuntu 18.04 中为 /tmp)。

然后,我们可以使用 std::filesystem::remove_all 显式删除创建的目录 当我们完成之后。

我不确定 C++ 标准是否能保证这一点,但 std::filesystem::temp_directory_path 极有可能调用 mkdir,它会自动尝试创建目录,并且如果它不会因 EEXIST 失败,因此我认为并行调用者之间不会存在竞争条件。

main.cpp

#include <exception>
#include <fstream>
#include <iostream>
#include <random>
#include <sstream>

#include <filesystem>

std::filesystem::path create_temporary_directory(
      unsigned long long max_tries = 1000) {
    auto tmp_dir = std::filesystem::temp_directory_path();
    unsigned long long i = 0;
    std::random_device dev;
    std::mt19937 prng(dev());
    std::uniform_int_distribution<uint64_t> rand(0);
    std::filesystem::path path;
    while (true) {
        std::stringstream ss;
        ss << std::hex << rand(prng);
        path = tmp_dir / ss.str();
        // true if the directory was created.
        if (std::filesystem::create_directory(path)) {
            break;
        }
        if (i == max_tries) {
            throw std::runtime_error("could not find non-existing directory");
        }
        i++;
    }
    return path;
}

int main() {
    auto tmpdir = create_temporary_directory();
    std::cout << "create_temporary_directory() = "
              << tmpdir
              << std::endl;

    // Use our temporary directory: create a file
    // in it and write to it.
    std::ofstream ofs(tmpdir / "myfile");
    ofs << "asdf\nqwer\n";
    ofs.close();

    // Remove the directory and its contents.
    std::filesystem::remove_all(tmpdir);
}

GitHub 上游

编译并运行:

g++-8 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp -lstdc++fs
./main.out

示例输出:

_directory.out
temp_directory_path() = "/tmp"
create_temporary_directory() = "/tmp/106adc08ff89874c"

对于文件,请参阅:如何在 C++ 中创建临时文本文件? 文件有点不同,因为 Linux 中的 openO_TMPFILE,其中 创建一个在关闭时自动消失的匿名 inode,因此专用临时文件 API 可以通过以下方式提高效率:使用那个。然而,mkdir 没有类似的标志,因此这个解决方案可能是最佳的。

在 Ubuntu 18.04 中测试。

C++17 std::filesystem::temp_directory_path + random number generation

Here is a pure C++17 solution that might be reliable: no Boost or other external libraries and no mkdtemp which is POSIX.

We just loop over random numbers until we are able to create a directory that did not exist before inside std::filesystem::temp_directory_path (/tmp in Ubuntu 18.04).

We can then explicitly remove the created directory with std::filesystem::remove_all after we are done with it.

I'm not sure that the C++ standard guarantees this, but is extremely likely that std::filesystem::temp_directory_path calls mkdir, which atomically tries to create the directory and if it can't fails with EEXIST, so I don't think there can be race conditions across parallel callers.

main.cpp

#include <exception>
#include <fstream>
#include <iostream>
#include <random>
#include <sstream>

#include <filesystem>

std::filesystem::path create_temporary_directory(
      unsigned long long max_tries = 1000) {
    auto tmp_dir = std::filesystem::temp_directory_path();
    unsigned long long i = 0;
    std::random_device dev;
    std::mt19937 prng(dev());
    std::uniform_int_distribution<uint64_t> rand(0);
    std::filesystem::path path;
    while (true) {
        std::stringstream ss;
        ss << std::hex << rand(prng);
        path = tmp_dir / ss.str();
        // true if the directory was created.
        if (std::filesystem::create_directory(path)) {
            break;
        }
        if (i == max_tries) {
            throw std::runtime_error("could not find non-existing directory");
        }
        i++;
    }
    return path;
}

int main() {
    auto tmpdir = create_temporary_directory();
    std::cout << "create_temporary_directory() = "
              << tmpdir
              << std::endl;

    // Use our temporary directory: create a file
    // in it and write to it.
    std::ofstream ofs(tmpdir / "myfile");
    ofs << "asdf\nqwer\n";
    ofs.close();

    // Remove the directory and its contents.
    std::filesystem::remove_all(tmpdir);
}

GitHub upstream.

Compile and run:

g++-8 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp -lstdc++fs
./main.out

Sample output:

_directory.out
temp_directory_path() = "/tmp"
create_temporary_directory() = "/tmp/106adc08ff89874c"

For files, see: How to create a temporary text file in C++? Files are a bit different because open in Linux has the O_TMPFILE, which creates an anonymous inode that automatically disappears on close, so dedicated temporary file APIs can be more efficient by using that. There is no analogous flag for mkdir however, so this solution might be optimal.

Tested in Ubuntu 18.04.

隔岸观火 2024-09-19 11:18:53

请在此处检查 mkdtemp 函数。

Check the mkdtemp function here.

情定在深秋 2024-09-19 11:18:53

Boost 的文件系统库提供了与平台无关的目录功能。它会稍微增加你的程序大小,但使用 Boost 通常比你自己开发更好(而且更容易)。

http://www.boost.org/doc/ libs/1_43_0/libs/filesystem/doc/index.htm

Boost's Filesystem library provides platform-independent directory functions. It will increase your program size a bit, but using Boost is often better (and often easier) than rolling your own.

http://www.boost.org/doc/libs/1_43_0/libs/filesystem/doc/index.htm

转身泪倾城 2024-09-19 11:18:53

没有标准函数可以执行此操作,因此您需要为每个目标平台编译不同的实现。

例如,在 Windows 上,您应该使用临时目录,可以通过调用 GetTempPath() 来获取该目录。

There's no standard function to do this, so you'll need to compile different implementations for each platform you target.

On Windows, for example, you should use the temp directory, which can be obtained by a call to GetTempPath().

自我难过 2024-09-19 11:18:53

mkdtemp(char *template)

http ://www.cl.cam.ac.uk/cgi-bin/manpage?3+mkdtemp

创建临时目录。

mkdtemp(char *template)

http://www.cl.cam.ac.uk/cgi-bin/manpage?3+mkdtemp

Creates a temporary directory.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文