How to check if file exists in C++ in a portable way? -
currently use code check if file exists on windows
, posix
-compatible oses (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; }
questions:
does code have pitfalls? (maybe os cannot compiled)
is possible in portable way using c/c++ standard library?
how improve it? looking canonical example.
because c++ tagged, use boost::filesystem
:
#include <boost/filesystem.hpp> bool fileexist( const std::string& name ) { return boost::filesystem::exists(name); }
behind scenes
apparently, boost using stat
on posix , dword attr(::getfileattributesw(filename));
on windows (note: i've extracted relevant parts of code here, did wrong, should it).
basically, besides return value, boost checking errno value in order check if file not exist, or stat failed different reason.
#ifdef boost_posix_api struct stat path_stat; if (::stat(p.c_str(), &path_stat)!= 0) { if (ec != 0) // report errno, though ec->assign(errno, system_category()); // errno values 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
defined separately windows , posix:
windows:
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 no card inserted || errval == error_not_ready // cd/dvd drive 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; }
Comments
Post a Comment