如何以可移植的方式检查C ++中是否存在文件?
目前,我使用此代码检查Windows
和POSIX
兼容的操作系统(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; }
问题:
-
这段代码有什么缺陷吗? (也许是一个无法编译的操作系统)
-
是否可以仅使用C / C ++标准库以真正可移植的方式进行?
-
如何改进? 寻找规范的例子。
因为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
应该是个问题。
- 这段代码有什么缺陷吗? (也许是一个无法编译的操作系统)
Result == 0
“跳过” ENAMETOOLONG
, ELOOP
,错误等
我能想到这个: ENAMETOOLONG
路径太长了: –
在许多情况下,在递归扫描期间,子文件夹/目录继续增加,如果路径“太长”,则可能导致此错误,但仍然存在文件!
其他错误也可能发生类似情况。
也,
据此 ,我更喜欢使用重载的boost::filesystem::exists
方法
bool exists(const path& p, system::error_code& ec) noexcept;