如何在创建新文件之前检查文件是否存在

How to check if a file exists before creating a new file

本文关键字:文件 检查 存在 是否 创建 新文件      更新时间:2023-10-16

我想在文件中输入一些内容,但我想先检查是否存在我想要创建的名称的文件。如果是这样,我不想创建任何文件,即使文件是空的。

我的尝试

bool CreateFile(char name[], char content[]){
     std::ofstream file(name);
     if(file){
         std::cout << "This account already exists" << std::endl;
        return false;
     }
     file << content;
     file.close();
     return true;
}

有办法做我想做的事吗

假设操作不是原子操作,则可以执行:

if (std::ifstream(name))
{
     std::cout << "File already exists" << std::endl;
     return false;
}
std::ofstream file(name);
if (!file)
{
     std::cout << "File could not be created" << std::endl;
     return false;
}
... 

请注意,如果您运行多个线程试图创建同一个文件,这是不起作用的,当然也不会阻止第二个进程"干扰"文件创建,因为您有TOCTUI问题。[我们首先检查文件是否存在,然后创建它——但其他人可能在检查和创建之间创建了它——如果这很关键,你需要做其他事情,这是不可移植的]。

另一个问题是,如果你有权限,比如文件是不可读的(所以我们不能打开它进行读取),但它是可写的,它会覆盖文件。

在大多数情况下,这两件事都不重要,因为你所关心的只是以"尽最大努力"的方式告诉别人"你已经有了这样的文件"(或类似的东西)。

您也可以使用Boost。

 boost::filesystem::exists( filename );

它适用于文件和文件夹。

您将有一个接近C++14的实现,其中文件系统应该是STL的一部分(请参阅此处)。

尝试

ifstream my_file("test.txt");
if (my_file)
{
 // do stuff
}

From:如何检查文件是否存在并且在C++中可读?

或者你可以使用助推功能。

试试这个(从Erik Garrison复制的ish:https://stackoverflow.com/a/3071528/575530)

#include <sys/stat.h>
bool FileExists(char* filename) 
{
    struct stat fileInfo;
    return stat(filename, &fileInfo) == 0;
}

如果文件存在,则stat返回0,如果不存在,则返回-1

从C++17开始,有:

if (std::filesystem::exists(pathname)) {
   ...

环顾四周,我唯一发现的是使用open系统调用。这是我发现的唯一一个功能,允许你以一种如果已经存在就会失败的方式创建文件

#include <fcntl.h>
#include <errno.h>
int fd=open(filename, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
if (fd < 0) {
  /* file exists or otherwise uncreatable
     you might want to check errno*/
}else {
  /* File is open to writing */
}

请注意,由于您正在创建文件,因此必须授予权限。

这也消除了任何可能存在的竞争条件

我刚刚看到了这个测试:

bool getFileExists(const TCHAR *file)
{ 
  return (GetFileAttributes(file) != 0xFFFFFFFF);
}

C++17,跨平台:使用std::filesystem::existsstd::filesystem::is_regular_file

#include <filesystem> // C++17
#include <fstream>
#include <iostream>
namespace fs = std::filesystem;
bool CreateFile(const fs::path& filePath, const std::string& content)
{
    try
    {
        if (fs::exists(filePath))
        {
            std::cout << filePath << " already exists.";
            return false;
        }
        if (!fs::is_regular_file(filePath))
        {
            std::cout << filePath << " is not a regular file.";
            return false;
        }
    }
    catch (std::exception& e)
    {
        std::cerr << __func__ << ": An error occurred: " << e.what();
        return false;
    }
    std::ofstream file(filePath);
    file << content;
    return true;
}
int main()
{
    if (CreateFile("path/to/the/file.ext", "Content of the file"))
    {
        // Your business logic.
    }
}

最简单的方法是使用ios :: noreplace