目前,我使用此代码检查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 ++标准库以真正可移植的方式进行?
如何改进?寻找规范的例子。
答案 0 :(得分:20)
因为C ++也被标记,我会使用boost::filesystem
:
#include <boost/filesystem.hpp>
bool FileExist( const std::string& Name )
{
return boost::filesystem::exists(Name);
}
幕后花絮
显然,在Windows上使用stat
和在Windows上使用DWORD attr(::GetFileAttributesW(FileName));
(注意:我在这里提取了代码的相关部分,可能是我做错了,但这应该是它)。
基本上,除了返回值之外,还会检查errno值以检查文件是否确实存在,或者您的统计信息因其他原因而失败。
#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;
}
答案 1 :(得分:2)
我只是想尝试打开文件:
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
应该是个问题。
答案 2 :(得分:1)