我想找到最快的方法来检查一个文件是否存在于标准c++ 11, 14, 17,或C。我有成千上万的文件,在对它们做一些事情之前,我需要检查它们是否都存在。在下面的函数中,我可以写什么来代替/* SOMETHING */ ?

inline bool exist(const std::string& name)
{
    /* SOMETHING */
}

当前回答

与PherricOxide的建议相同,但在C中

#include <sys/stat.h>
int exist(const char *name)
{
  struct stat   buffer;
  return (stat (name, &buffer) == 0);
}

其他回答

与PherricOxide的建议相同,但在C中

#include <sys/stat.h>
int exist(const char *name)
{
  struct stat   buffer;
  return (stat (name, &buffer) == 0);
}

备注:在c++ 14中,一旦文件系统TS完成并被采用,解决方案将使用:

std::experimental::filesystem::exists("helloworld.txt");

从c++ 17开始,只有:

std::filesystem::exists("helloworld.txt");
inline bool exist(const std::string& name)
{
    ifstream file(name);
    if(!file)            // If the file was not found, then file is 0, i.e. !file=1 or true.
        return false;    // The file was not found.
    else                 // If the file was found, then file is non-0.
        return true;     // The file was found.
}
all_of (begin(R), end(R), [](auto&p){ exists(p); })

其中R是你的路径序列,exists()来自未来std或当前boost。如果你自己卷,简单点,

bool exists (string const& p) { return ifstream{p}; }

分支解决方案并不是绝对可怕的,它不会吞噬文件描述符,

bool exists (const char* p) {
    #if defined(_WIN32) || defined(_WIN64)
    return p && 0 != PathFileExists (p);
    #else
    struct stat sb;
    return p && 0 == stat (p, &sb);
    #endif
}

测试文件是否存在的最快和最安全的方法是根本不单独/显式地测试它。也就是说,看看你是否能找到一种方法来取代普通

if(exists(file)) {                           /* point A */
    /* handle existence condition */
    return;
}

do_something_with(file);                     /* point B */

随着

r = do_something_with_unless_exists(file);

if(r == 0)
    success;
else if(errno == EEXIST)
    /* handle existence condition */
else
    /* handle other error */

除了速度更快之外,这还消除了第一个解决方案中固有的竞争条件(特别是“TOC/TOU”),即文件在点A和点B之间存在的可能性。

显然,第二个解决方案假定存在一种原子方法来执行do_something_with_unless_exists操作。通常总会有办法的,但有时你得四处寻找。

创建文件:使用O_CREAT和O_EXCL调用open()。 创建一个纯C文件,如果你有C11:调用fopen()与"wx"。(我昨天才知道这个。) 创建目录:只需调用mkdir(),然后检查errno == EEXIST。 获取锁:任何称职的锁定系统都已经拥有一个原子性的“只要没有其他人拥有就获取锁”原语。

(还有其他的,但这些是我现在能想到的。)

[脚注:在Unix的早期,没有特定的、专用的工具可用于普通进程进行锁定,所以如果你想建立一个互斥锁,这通常是通过创建一个特定的空目录来实现的,因为mkdir系统调用总是能够根据先前的存在或不存在而原子地失败或成功。]