如何在创建新文件之前检查文件是不是存在
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::exists
和std::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最简单的方法是使用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
,因此fopen
和fstream
不能一起工作。此外,如果文件已经存在,则没有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 函数。
【讨论】:
如果您没有对该文件的读取权限,这可能不起作用。当然,大多数情况下您无论如何都无法写入 - 但有些系统具有奇怪的权限,您可能拥有没有读取权限的写入权限,从而破坏了您的文件。以上是关于如何在创建新文件之前检查文件是不是存在的主要内容,如果未能解决你的问题,请参考以下文章
在 Rails 中如何在使用 javascript_include_tag 之前检查 javascript 文件是不是存在