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

Posted

技术标签:

【中文标题】如何在创建新文件之前检查文件是不是存在【英文标题】:How to check if a file exists before creating a new file如何在创建新文件之前检查文件是否存在 【发布时间】:2013-07-22 23:45:13 【问题描述】:

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

我的尝试

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;

有什么方法可以做我想做的事吗?

【问题讨论】:

...先尝试打开阅读? 第二种方法是检查路径是否存在fstat() 我知道 Windows 允许您将其作为 CreateFile 中的原子操作来处理。我希望其他常见系统具有相同的行为。 C++ 标准库中肯定有可用的抽象吗? 你也应该检查这个:***.com/questions/12774207/… 【参考方案1】:

环顾了一下,我发现唯一的事情是使用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 */

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

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

【讨论】:

当然,现在你的问题是不能将文件用作fstream,而且这只适用于Unix风格的操作系统。 好吧,既然你已经创建了它,你可以随时关闭它并重新打开它(你现在“拥有”它 - 你确定你创建了它)。至于 unix 的东西 - 不知道!我从来没有在windows上编程过。但是 google 在 msdn 中找到了 CreateFile 函数,如果文件存在,则给定 CREATE_NEW 标志将失败。所以我想你可以用#define 来为不同的操作系统做到这一点......真的应该有一个标准的方法来做到这一点<.>【参考方案2】:

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.
    

【讨论】:

【参考方案3】:

从 C++17 开始有:

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

【讨论】:

只用了 19 年...xD 使用 msvc 14 的语法是:#include ... return std::experimental::filesystem::exists(filename);【参考方案4】:

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

【讨论】:

没有这样的东西。【参考方案5】:

我刚刚看到了这个测试:

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

【讨论】:

【参考方案6】:

您也可以使用 Boost。

 boost::filesystem::exists( filename );

它适用于文件和文件夹。

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

【讨论】:

迄今为止的最佳答案 +1 跨平台【参考方案7】:

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

#include <sys/stat.h>

bool FileExists(char* filename) 

    struct stat fileInfo;
    return stat(filename, &fileInfo) == 0;

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

【讨论】:

这不只适用于 Linux (POSIX) 吗?它是否也适用于标准 MinGW 安装?【参考方案8】:

假设操作不是原子的就可以了,你可以这样做:

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 问题。 [我们首先检查文件是否存在,然后创建它——但其他人可能在检查和创建之间创建了它——如果这很关键,你将需要做一些其他不可移植的事情]。

另一个问题是,如果您有权限,例如文件不可读(因此我们无法打开它进行读取)但可写,它将覆盖文件。

在大多数情况下,这些事情都不重要,因为您所关心的只是以“尽力而为”的方式告诉某人“您已经拥有类似的文件”(或类似的文件)。

【讨论】:

不(总是)工作,即使没有竞争条件。如果文件有写权限但没有读权限,您的示例将覆盖它。 @MatsPetersson,仅供参考 - 在“C 和 C++ 中的安全编码”(Robert Seacord)第 2 版第 8 章第 5 节中相当广泛地讨论了这种竞争条件。 @NathanErnst:这是一个众所周知的问题。但只有当您处理直接具有安全方面的文件(“/etc/passwd”或类似的东西)或应用程序本身具有安全方面时,这才是一个问题。对于大多数应用程序来说,尝试打开以进行读取然后打开以进行写入就足够了,因为无论如何都没有竞争相同的文件名 - 这只是提醒“您已经使用过该名称,请选择另一个”。 @MatsPetersson,同意。不幸的是,即使查看 C++11 标准库,似乎也没有办法直接解决这个问题。您不能从文件描述符构造basic_filebuf,因此fopenfstream 不能一起工作。此外,如果文件已经存在,则没有openmode 标志可用于失败(假设您也拥有该文件的权限)。我能看到的最好的方法是以附加模式打开并针对 0 测试 tellp,我什至不确定这是否安全或正确。 @NathanErnst:以附加模式打开不会阻止它使用空文件(但存在)。但我认为这里的问题是“支持许多操作系统架构” - 有些操作系统根本不支持以“工作”的方式打开文件(你必须采取其他措施来防止覆盖文件 - 显然,这差不多意味着它不是一个非常安全的系统,但 C++ 作为一种语言不需要安全性...)。【参考方案9】:

试试

ifstream my_file("test.txt");
if (my_file)

 // do stuff

发件人:How to check if a file exists and is readable in C++?

或者你可以使用 boost 函数。

【讨论】:

如果您没有对该文件的读取权限,这可能不起作用。当然,大多数情况下您无论如何都无法写入 - 但有些系统具有奇怪的权限,您可能拥有没有读取权限的写入权限,从而破坏了您的文件。

以上是关于如何在创建新文件之前检查文件是不是存在的主要内容,如果未能解决你的问题,请参考以下文章

在 JSP 中包含/导入文件之前,如何检查文件是不是存在?

如果创建文件不存在,如何创建目录?

在 Rails 中如何在使用 javascript_include_tag 之前检查 javascript 文件是不是存在

如何检查下载的文件是不是存在

如何检查会话是不是存在?

安卓;检查文件是不是存在而不创建新文件