使用 O_EXCL 创建文件的 iostream C++是什么?

What is the C++ iostream to creating a file with O_EXCL?

提问人:vy32 提问时间:10/5/2021 更新时间:1/29/2023 访问量:328

问:

我想以线程安全的方式创建一个输出文件,并且仅在它不存在的情况下。我想使用文件系统进行同步。我会使用标志.有没有办法在 C++17 中使用 or ?open()O_RWRONLY|O_CREAT|O_EXCLiostreamfstream

C++17 Fstream IOSTREAM ofstream

评论

0赞 yeputons 10/5/2021
不,它是特定于操作系统的东西。
0赞 Davis Herring 10/7/2021
C23 和 C++23 正在考虑在各自的标准库中对此提供适当的支持。POSIX 当然与 一起定义,但没有可移植的 C++ 等价物。fdopenO_EXCL
1赞 vy32 10/8/2021
谢谢。如果您参与 C++23,那么最好有一种基于标准的方式来执行内存映射文件。

答:

2赞 Ted Lyngmo 10/5/2021 #1

在 C++23 之前,无法打开独占模式。ofstream

解决方法:使用 std::fopen,它从 C++17 开始具有此功能。

例:

#include <cstdio>

// Mode "x" to make it fail if it already exists
std::FILE* fp = std::fopen("filename", "wx");

if(fp) {
    // created exclusively

    // work with fp ...

    std::fclose(fp);
}

如果你真的想要一个,你可以创建一个帮助函数:ofstream

template<class Stream>
Stream open_exclusively(const std::string& filename) {
    Stream rv;
    
    if(std::FILE* fp = std::fopen(filename.c_str(), "wx"); fp) {
        std::fclose(fp);

        // overwrite the file that was created exclusively:
        rv.open(filename);
    } else {
        // could not create file exclusivly, set the failbit in the stream:
        rv.setstate(Stream::failbit);
    }

    return rv;
}

int main() {
    auto os = open_exclusively<std::ofstream>("filename");

    if(os) {
        std::cout << "file created exclusively\n";
    }
}

演示

编辑:

尽管上面的演示是兼容的并且适用于所有平台,但我已经测试过了 - (v6.16) 无法处理它,所以我在 bugs.winehq.org 打开了错误报告。您可以在此处跟踪进度:wine

无法识别标准库调用 fopen(..., “wx”) - 导致数据破坏

编辑2:

Wine 错误修复 ucrtbase: Add support for x mode in fopen 现在包含在 Wine 6.20 中,因此在升级到 6.20(或更高版本)后,它也将在 Wine 中正常工作。


从 C++23 开始,您可以使用 openmodestd::ios::noreplace

std::ofstream os("filename", std::ios::noreplace);

if(os) {
    std::cout << "file created exclusively\n";
}

评论

0赞 vy32 10/5/2021
这适用于带有 mingw 的 WIN32 吗?
1赞 Ted Lyngmo 10/5/2021
@vy32 如果它完全符合 C++17,是的。
0赞 vy32 10/5/2021
伟大。我会试一试。谢谢!我希望这需要一段时间,但我想我不能拥有一切。fclose()std::string
0赞 Ted Lyngmo 10/5/2021
@vy32 :-)True - / 是 C 的遗留问题 - 但它有其用途,就像在这种情况下一样。fopenfclose
0赞 vy32 10/5/2021
可悲的是,它不符合 C++17 标准。我收到以下错误消息: .(在 Wine 下运行)00fc:err:msvcrt:msvcrt_get_flags incorrect mode flag: x