【问题标题】:How to check if a file exists and is readable in C++?如何检查文件是否存在并且在 C++ 中是否可读?
【发布时间】:2010-11-25 21:34:15
【问题描述】:

我有一个 fstream my_file("test.txt"),但我不知道 test.txt 是否存在。如果它存在,我想知道我是否也可以阅读它。该怎么做?

我使用 Linux。

【问题讨论】:

    标签: c++ linux file fstream exists


    【解决方案1】:

    我可能会选择:

    ifstream my_file("test.txt");
    if (my_file.good())
    {
      // read away
    }
    

    good 方法检查流是否准备好被读取。

    【讨论】:

    • 这样,您不仅可以检查它是否存在且是否可读,还可以实际打开它。
    • 是的,没错。我阅读了 OP 的问题,即文件已经打开,但我可能是错的。
    • 而且无法判断是文件不存在还是访问权限问题无法打开。
    【解决方案2】:

    您可以使用Boost.Filesystem。它有一个boost::filesystem::exist 函数。

    我不知道如何检查读取访问权限。你也可以查看Boost.Filesystem。然而,除了尝试实际读取文件之外,可能没有其他(便携式)方法。

    编辑(2021-08-26): C++17 引入了<filesystem>,你有std::filesystem::exists。不再需要 Boost。

    【讨论】:

    • boost 文件系统是否在 windows (> 256) 上处理非常长的路径?我们最近遇到了非 unicode windows API 最多 256 个字符的问题。
    • 我不知道。您可以查看文档(在我的答案中的链接),但我不确定您是否会找到它并且它很长。您也可以在 Boost 新闻组上提问。另一种方法是简单地检查它。
    • @Richard Corden 我用函数 boost::filesystem::create_directories 检查了很长的路径。如果给定长路径,ANSI 版本(用于 char)会引发异常(但限制以某种方式达到了 250 左右,而不是等于 260 的 MAX_PATH)。 UNICODE 版本(用于 wchar_t)创建了与 ANSI 版本一样多的文件夹而不会抛出并成功返回,因此它不仅没有完成这项工作,而且它也没有报告错误。我不知道其他功能的情况如何,但我怀疑它们现在可能表现不佳。
    【解决方案3】:

    如果您使用的是 unix,那么 access() 可以告诉您它是否可读。但是,如果 ACL 正在使用中,那么它会变得更加复杂,在这种情况下,最好使用 ifstream 打开文件并尝试读取。如果无法读取,则 ACL 可能会禁止读取。

    【讨论】:

    • access() 是引入检查时间到使用时间错误的好方法。
    【解决方案4】:

    什么操作系统/平台?

    在 Linux/Unix/MacOSX 上,您可以使用fstat

    在 Windows 上,您可以使用GetFileAttributes

    通常,使用标准 C/C++ IO 函数没有可移植的方法。

    【讨论】:

    • 为什么这么说,你总是可以尝试用 fopen 打开一个文件,如果它返回 0,你可以推断出该文件不存在。
    • fstat 在 Windows 上也可用,在 sys/stat.h 中。
    • @Blindy 或者它确实存在,但您无权访问它。然后怎样呢? :q 你的推论是错误的。
    • @sasq 没有区别,标题字面意思是“并且可读”。根据定义,您无权访问的文件是不可读的。批判性思维会让你在生活中走得更远!
    • @Blindy 我指的是您的评论,而不是标题或原始帖子。我的观点是,打开一个文件只是为了检查它是否存在可能会产生人们不一定想要的副作用,包括意外损坏文件的可能性(例如,如果一个人也打开它进行写入并且碰巧它存在)。并让我成为“批判性思维”的广告人。
    【解决方案5】:

    C++17,跨平台:使用std::filesystem::exists 检查文件是否存在,使用std::filesystem::statusstd::filesystem::perms 检查文件的可读性:

    #include <iostream>
    #include <filesystem> // C++17
    namespace fs = std::filesystem;
    
    /*! \return True if owner, group and others have read permission,
                i.e. at least 0444.
    */
    bool IsReadable(const fs::path& p)
    {
        std::error_code ec; // For noexcept overload usage.
        auto perms = fs::status(p, ec).permissions();
        if ((perms & fs::perms::owner_read) != fs::perms::none &&
            (perms & fs::perms::group_read) != fs::perms::none &&
            (perms & fs::perms::others_read) != fs::perms::none
            )
        {
            return true;
        }
        return false;
    }
    
    int main()
    {
        fs::path filePath("path/to/test.txt");
        std::error_code ec; // For noexcept overload usage.
        if (fs::exists(filePath, ec) && !ec)
        {
            if (IsReadable(filePath))
            {
                std::cout << filePath << " exists and is readable.";
            }
        }
    }
    

    考虑同时检查file type

    【讨论】:

    • 很好的答案,但很快的问题:我们如何检查此可执行文件是否有权读取文件,而不是谁有权读取文件我>?
    【解决方案6】:

    从 C++11 开始,可以使用隐式 operator bool 代替 good()

    ifstream my_file("test.txt");
    if (my_file) {
      // read away
    }
    

    【讨论】:

      【解决方案7】:

      我知道发帖人最终说他们使用的是 Linux,但我有点惊讶没有人提到 Windows 的 PathFileExists() API 调用。

      您需要包含Shlwapi.lib 库和Shlwapi.h 头文件。

      #pragma comment(lib, "shlwapi.lib")
      #include <shlwapi.h>
      

      该函数返回一个BOOL 值,可以这样调用:

      if( PathFileExists("C:\\path\\to\\your\\file.ext") )
      {
          // do something
      }
      

      【讨论】:

      【解决方案8】:

      关于在 Windows 中使用 fstat,我不确定它是否是您想要的。来自Microsoft 的文件必须已经打开。 Stat 应该适合你。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-08-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-24
        • 2012-08-07
        • 2015-04-28
        相关资源
        最近更新 更多