C++ 编号的唯一文件

C++ 编号的唯一文件,c++,file,C++,File,我想创建唯一的文件,必要时在文件名后面加上一个数字(类似于浏览器通常命名下载文件的方式) 以下是我试图做的事情,但涉及目录(使用库): #包括 名称空间fs=std::filesystem; 模板std::字符串连接(Args&&…Args){ std::ostringstream sstr; (sstr对于目录,您正在检查目录的创建是否有效。对于文件,您可以通过检查特定路径是否指向文件来实现此效果,如果不是,则创建它: fs::path unique_file(const fs::path &

我想创建唯一的文件,必要时在文件名后面加上一个数字(类似于浏览器通常命名下载文件的方式)

以下是我试图做的事情,但涉及目录(使用库):

#包括
名称空间fs=std::filesystem;
模板std::字符串连接(Args&&…Args){
std::ostringstream sstr;

(sstr对于目录,您正在检查目录的创建是否有效。对于文件,您可以通过检查特定路径是否指向文件来实现此效果,如果不是,则创建它:

fs::path unique_file(const fs::path &base, unsigned max_tries) {
    if(!fs::exists(base)) {
       std::ofstream ofs(base);
       return base;
    }

    for(unsigned i = 1; i < max_tries; ++i) {
        fs::path p = base;
        p += concat() << '_' << i;

        if(!fs::exists(p)) {
            std::ofstream ofs(p);
            return p;
        }
    }

    throw std::runtime_error("unique_file: gave up");
}
fs::path unique\u文件(常量fs::path&base,无符号最大重试次数){
如果(!fs::exists(base)){
标准::ofs流(基础);
返回基地;
}
for(无符号i=1;ip+=concat()对于目录,您正在检查目录的创建是否有效。对于文件,您可以通过检查特定路径是否指向文件来实现此效果,如果不是,则创建它:

fs::path unique_file(const fs::path &base, unsigned max_tries) {
    if(!fs::exists(base)) {
       std::ofstream ofs(base);
       return base;
    }

    for(unsigned i = 1; i < max_tries; ++i) {
        fs::path p = base;
        p += concat() << '_' << i;

        if(!fs::exists(p)) {
            std::ofstream ofs(p);
            return p;
        }
    }

    throw std::runtime_error("unique_file: gave up");
}
fs::path unique\u文件(常量fs::path&base,无符号最大重试次数){
如果(!fs::exists(base)){
标准::ofs流(基础);
返回基地;
}
for(无符号i=1;ip+=concat()以下是POSIX系统的解决方案,使用:

#include//open()
#include//close()
fs::path unique_文件(常量fs::path&base,未签名的最大重试次数){
路径p(基);

对于(无符号i=1;i,以下是POSIX系统的解决方案,使用:

#include//open()
#include//close()
fs::path unique_文件(常量fs::path&base,未签名的最大重试次数){
路径p(基);

对于(unsigned i=1;i您可能希望先让一个较小的程序工作,打印出随机文件名。先让这个程序工作。工作完成后,您可以将文件名传递给相应的函数。您可能希望先让一个较小的程序工作,打印出随机文件名。先让这个程序工作。工作完成后,您可以可以将文件名传递给相应的函数。如果我没有弄错的话,我会遇到另一个程序实例同时调用fs::exists()并使用相同的文件名的风险(尽管风险很小)。没有办法避免这种风险吗?是的,我相信这是真的(但不是100%确定)。因为这里不关心性能(如问题中所述),所以您可以在这里手动设置锁。是否有在进程(而不仅仅是线程)之间工作的锁?很抱歉,但我对这一点不太了解。我想这是可能的,但我不知道如何实现。在寻找跨进程锁时,我偶然发现了一个函数,可以在Linux上打开一个文件,但如果它存在,则会失败()。现在我只需要在其他平台上寻找等效的。谢谢你的帮助!如果我没有弄错的话,我会遇到另一个程序实例同时调用fs::exists()并使用相同的文件名的风险(尽管很小)。没有办法避免这种风险吗?是的,我相信这是真的(但不是100%确定)。因为这里不关心性能(如问题中所述),所以您可以在这里手动设置锁。是否有在进程(而不仅仅是线程)之间工作的锁?很抱歉,但我对这一点不太了解。我想这是可能的,但我不知道怎么做。在寻找跨进程锁的时候,我偶然发现了一个函数,可以在Linux上打开一个文件,但如果它存在()就会失败。现在我只需要在其他平台上寻找等效的。谢谢你的帮助!
#include <fcntl.h> // open()
#include <unistd.h> // close()

fs::path unique_file(const fs::path &base, unsigned max_tries) {
    fs::path p(base);

    for(unsigned i = 1; i <= max_tries; ++i) {
        // O_CREAT | O_EXCL will create the file if it does not exist, and fail otherwise
        // 0666 : Read + Modify permissions for everybody
        int fd = open(p.c_str(), O_CREAT | O_EXCL, 0666);
        if(fd != -1) {
            if(close(fd) == -1) // We immediately close the file, which might be a waste
                throw fs::filesystem_error("unique_file: POSIX close() error", p, std::error_code(errno, std::generic_category()));

            return p;
        }

        // EEXIST is set if open() failed because the file already existed
        if(errno != EEXIST)
            throw fs::filesystem_error("unique_file: POSIX open() error", p, std::error_code(errno, std::generic_category()));

        errno = 0;
        p = base.parent_path() / base.stem();
        p += concatenate('_', i);
        p += base.extension();
    }

    throw std::runtime_error("unique_file: gave up");
}