現在、このコードを使用して、ファイルがWindows
およびPOSIX
互換のOS(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;
}
質問:
このコードには落とし穴がありますか? (たぶんコンパイルできないOS)
C/C++標準ライブラリのみを使用して、真に移植可能な方法でそれを行うことは可能ですか?
それを改善する方法は?正規の例を探しています。
C++にもタグが付けられているので、_boost::filesystem
_を使用します。
_#include <boost/filesystem.hpp>
bool FileExist( const std::string& Name )
{
return boost::filesystem::exists(Name);
}
_
舞台裏
どうやら、boostはPOSIXではstat
を使用し、WindowsではDWORD attr(::GetFileAttributesW(FileName));
を使用しているようです(注:ここでコードの関連部分を抽出しました。何か間違ったことをした可能性がありますが、これはそれ)。
基本的に、boostは戻り値に加えて、ファイルが実際に存在しないかどうか、または別の理由で統計が失敗したかどうかを確認するために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;
}
_
私はいつもファイルを開こうとするのが好きです:
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
_ "skips" ENAMETOOLONG
、ELOOP
、エラーなど this
私はこれを考えることができます:ENAMETOOLONG
パスは長すぎます:-
多くの場合、再帰スキャン中にサブフォルダ/ディレクトリは増加し続けます。パスが「長すぎる」場合、このエラーが発生する可能性がありますが、ファイルはまだ存在します。
同様のケースが他のエラーでも発生する可能性があります。
また、
this のように、オーバーロードされた_boost::filesystem::exists
_メソッドを使用することをお勧めします
bool exists(const path& p, system::error_code& ec) noexcept;