【问题标题】:How can I tell if a given path is a directory or a file? (C/C++)如何判断给定路径是目录还是文件? (C/C++)
【发布时间】:2010-09-13 21:35:20
【问题描述】:

我正在使用 C,有时我必须处理类似的路径

  • C:\随便
  • C:\随便\
  • C:\Whatever\Somefile

有没有办法检查给定路径是目录还是给定路径是文件?

【问题讨论】:

    标签: c++ c winapi


    【解决方案1】:

    stat() 会告诉你这个。

    struct stat s;
    if( stat(path,&s) == 0 )
    {
        if( s.st_mode & S_IFDIR )
        {
            //it's a directory
        }
        else if( s.st_mode & S_IFREG )
        {
            //it's a file
        }
        else
        {
            //something else
        }
    }
    else
    {
        //error
    }
    

    【讨论】:

    • 我对这段代码的唯一问题是 else 情况下的注释。仅仅因为某些东西不是目录并不意味着它是一个文件。
    • @dicroce:是的,确实如此;固定。
    • 当我尝试使用它时,我得到“聚合 'main(int, char**)::stat s' 类型不完整,无法定义”,真的无法得到错误是什么.它首先在 struct stat s 行中给出错误;我的错误可能是什么?
    • 好的,我需要添加#include 我的错 :)
    • 是否有支持宽字符路径的重载或类似函数?
    【解决方案2】:

    调用 GetFileAttributes,并检查 FILE_ATTRIBUTE_DIRECTORY 属性。

    【讨论】:

    • 如果需要支持Windows 98,则不能使用该功能。如果您需要 Win98 支持,请参阅下面关于 PathIsDirectory 的回答。
    【解决方案3】:

    使用 C++14/C++17,您可以使用来自filesystem library 的独立于平台的is_directory()is_regular_file()

    #include <filesystem> // C++17
    #include <iostream>
    namespace fs = std::filesystem;
    
    int main()
    {
        const std::string pathString = "/my/path";
        const fs::path path(pathString); // Constructing the path from a string is possible.
        std::error_code ec; // For using the non-throwing overloads of functions below.
        if (fs::is_directory(path, ec))
        { 
            // Process a directory.
        }
        if (ec) // Optional handling of possible errors.
        {
            std::cerr << "Error in is_directory: " << ec.message();
        }
        if (fs::is_regular_file(path, ec))
        {
            // Process a regular file.
        }
        if (ec) // Optional handling of possible errors. Usage of the same ec object works since fs functions are calling ec.clear() if no errors occur.
        {
            std::cerr << "Error in is_regular_file: " << ec.message();
        }
    }
    

    在 C++14 中使用std::experimental::filesystem

    #include <experimental/filesystem> // C++14
    namespace fs = std::experimental::filesystem;
    

    section "File types" 中列出了其他已实施的检查。

    【讨论】:

    • 嗨@Roi Danton,感谢您的回答。你知道为什么这在 macOS 上不起作用吗?似乎与 Clang 不支持此库有关。非常不幸,IMO。
    • @mannygover Clang 支持std::filesystem。确保使用带有选项-std=c++17 的Clang 7 或更高版本。 Minimal example at compiler explorer.
    【解决方案4】:

    在 Win32 中,我通常使用PathIsDirectory 及其姐妹函数。这适用于 Windows 98,而 GetFileAttributes 不适用(根据 MSDN 文档。)

    【讨论】:

    • 我没试过,但最早的文档版本是随 Windows 95 分发的,所以可能不是。
    • 你当然可以在 Windows 98 中使用GetFileAttributes(),而且据信它早于PathIsDirectory() 的存在。在检查 API 的最低操作系统要求时,您不能依赖 MSDN 文档,因为 MSDN 撒谎!当 MS 放弃对某个操作系统版本的支持时,他们希望从 MSDN 文档中删除对它的大部分引用,尤其是在现有 API 的最低操作系统要求方面。
    【解决方案5】:

    在 Windows 上,您可以在 open handle 上使用 GetFileAttributes

    【讨论】:

      【解决方案6】:

      这是使用GetFileAttributesW 函数检查路径是否为Windows 上的目录的简单方法。如果接收到的路径必须是目录或文件路径,那么如果不是目录路径,则可以假定它是文件路径。

      bool IsDirectory(std::wstring path)
      {
          DWORD attrib = GetFileAttributes(path.c_str());
      
          if ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
              return true;
      
          return false;
      }
      

      【讨论】:

        【解决方案7】:

        如果你使用CFile,你可以试试

        CFileStatus status;
            if (CFile::GetStatus(fileName, status) && status.m_attribute == 0x10){
               //it's directory
        }
        

        【讨论】:

          【解决方案8】:

          在 qt 中更容易尝试 FileInfo.isDir()

          【讨论】:

          • 您能解释一下为什么在文件系统访问存在问题时使用 GUI 库吗?
          • 谢谢,这正是我想要的。 (通过谷歌。)
          • 你到底为什么“拖”到这里?
          猜你喜欢
          • 1970-01-01
          • 2013-04-28
          • 2012-07-17
          • 2010-11-03
          • 1970-01-01
          • 2015-07-30
          • 1970-01-01
          • 2011-12-26
          • 2017-05-01
          相关资源
          最近更新 更多