如何以可移植的方式检查C ++中是否存在文件?

目前,我使用此代码检查WindowsPOSIX兼容的操作系统(Linux,Android,MacOS,iOS,BlackBerry 10)上是否存在文件:

 bool FileExist( const std::string& Name ) { #ifdef OS_WINDOWS struct _stat buf; int Result = _stat( Name.c_str(), &buf ); #else struct stat buf; int Result = stat( Name.c_str(), &buf ); #endif return Result == 0; } 

问题:

  1. 这段代码有什么缺陷吗? (也许是一个无法编译的操作系统)

  2. 是否可以仅使用C / C ++标准库以真正可移植的方式进行?

  3. 如何改进? 寻找规范的例子。

因为C ++也被标记,我会使用boost::filesystem

 #include  bool FileExist( const std::string& Name ) { return boost::filesystem::exists(Name); } 

在幕后

显然,boost是在POSIX和DWORD attr(::GetFileAttributesW(FileName));上使用stat DWORD attr(::GetFileAttributesW(FileName)); 在Windows上(注意:我在这里提取了相关的代码部分,可能是我做错了,但应该是这样)。

基本上,除了返回值之外,boost还会检查errno值以检查文件是否确实存在,或者您的stat因其他原因而失败。

 #ifdef BOOST_POSIX_API struct stat path_stat; if (::stat(p.c_str(), &path_stat)!= 0) { if (ec != 0) // always report errno, even though some ec->assign(errno, system_category()); // errno values are not status_errors if (not_found_error(errno)) { return fs::file_status(fs::file_not_found, fs::no_perms); } if (ec == 0) BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status", p, error_code(errno, system_category()))); return fs::file_status(fs::status_error); } #else DWORD attr(::GetFileAttributesW(p.c_str())); if (attr == 0xFFFFFFFF) { int errval(::GetLastError()); if (not_found_error(errval)) { return fs::file_status(fs::file_not_found, fs::no_perms); } } #endif 

not_found_error是针对Windows和POSIX单独定义的:

视窗:

 bool not_found_error(int errval) { return errval == ERROR_FILE_NOT_FOUND || errval == ERROR_PATH_NOT_FOUND || errval == ERROR_INVALID_NAME // "tools/jam/src/:sys:stat.h", "//foo" || errval == ERROR_INVALID_DRIVE // USB card reader with no card inserted || errval == ERROR_NOT_READY // CD/DVD drive with no disc inserted || errval == ERROR_INVALID_PARAMETER // ":sys:stat.h" || errval == ERROR_BAD_PATHNAME // "//nosuch" on Win64 || errval == ERROR_BAD_NETPATH; // "//nosuch" on Win32 } 

POSIX:

 bool not_found_error(int errval) { return errno == ENOENT || errno == ENOTDIR; } 

我只是想尝试打开文件:

 bool FileExist( const std::string& Name ) { std::ifstream f(name.c_str()); // New enough C++ library will accept just name return f.is_open(); } 

应该处理任何有文件的东西[不是C ++标准所要求的],因为它使用的是C ++ std::string ,我不明白为什么std::ifstream应该是个问题。

  1. 这段代码有什么缺陷吗? (也许是一个无法编译的操作系统)

Result == 0 “跳过” ENAMETOOLONGELOOP ,错误等

我能想到这个: ENAMETOOLONG路径太长了: –

在许多情况下,在递归扫描期间,子文件夹/目录继续增加,如果路径“太长”,则可能导致此错误,但仍然存在文件!

其他错误也可能发生类似情况。

也,

据此 ,我更喜欢使用重载的boost::filesystem::exists方法

bool exists(const path& p, system::error_code& ec) noexcept;