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

Ser*_* K. 13 c c++ portability posix file

目前我使用此代码来检查,如果文件存在于WindowsPOSIX兼容操作系统(Linux操作系统,Android的,MacOS的,的iOS,黑莓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;
}
Run Code Online (Sandbox Code Playgroud)

问题:

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

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

  3. 怎么改进呢?寻找规范的例子.

Nem*_*ric 20

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

#include <boost/filesystem.hpp>

bool FileExist( const std::string& Name )
{
     return boost::filesystem::exists(Name);
}
Run Code Online (Sandbox Code Playgroud)

在幕后

显然,boost正在statPOSIX和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
Run Code Online (Sandbox Code Playgroud)

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
  }
Run Code Online (Sandbox Code Playgroud)

POSIX:

bool not_found_error(int errval)
  {
    return errno == ENOENT || errno == ENOTDIR;
  }
Run Code Online (Sandbox Code Playgroud)

  • 升力为+1.但是只使用Boost来实现这个功能(我们不会将Boost用于其他任何东西)有点贪心. (7认同)
  • @SergeyK.:内部类似于您的代码,不同平台的实现方式不同.该库(明年将成为标准库的一部分)提供了一个可移植的界面来实现这种肮脏. (3认同)