【问题标题】:c++ folder only searchc++文件夹只搜索
【发布时间】:2017-10-05 15:01:02
【问题描述】:

我需要获取目录中的文件夹列表,但只有文件夹。不需要文件。只有文件夹。我使用过滤器来确定这是否是一个文件夹,但它们不起作用并且所有文件和文件夹都被输出。

string root = "D:\\*";
cout << "Scan " << root << endl;
std::wstring widestr = std::wstring(root.begin(), root.end());
const wchar_t* widecstr = widestr.c_str();
WIN32_FIND_DATAW wfd;
HANDLE const hFind = FindFirstFileW(widecstr, &wfd);

这样,我检查它是不是一个文件夹。

if (INVALID_HANDLE_VALUE != hFind)
    if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))

如何解决问题?

【问题讨论】:

  • 对#include 和 DIR 发誓
  • Windows 当前不支持此功能。您可以将 fSearchOp 设置为 FindExSearchLimitToDirectories FindFirstFileEx - 但此标志现在无效
  • RbMm,请帮帮我。如何实现您在我的示例中描述的内容?
  • @Xom9ik - 检查FILE_ATTRIBUTE_DIRECTORY。你已经这样做了。和FindFirstFileExW(使用FIND_FIRST_EX_LARGE_FETCHFindExInfoBasic 更快。如果使用ZwQueryDirectoryFile 的异步句柄而不等待结果但一次有多个查询,则可以使速度提高几倍(在ssd 磁盘上)跨度>

标签: c++ winapi directory


【解决方案1】:

有两种方法可以做到这一点:困难的方法和简单的方法。

困难的方法是基于FindFirstFileFindNextFile,根据需要过滤掉目录。您会在 Stack Overflow 和互联网的其他地方找到大量概述这种方法的示例。

简单的方法:使用标准的directory_iterator 类(或recursive_directory_iterator,如果您需要递归到子目录)。解决方法很简单1

for ( const auto& entry : directory_iterator( path( L"abc" ) ) ) {
    if ( is_directory( entry.path() ) ) {
        // Do something with the entry
        visit( entry.path() );
    }
}

您必须包含在 C++17 中引入的 <filesystem> 头文件。

注意:使用最新版本的 Visual Studio 2017 (15.3.5),这在 namespace std 中还没有。您必须改为引用 namespace std::experimental::filesystem


1特别注意,不需要过滤掉... 伪目录;这些不是由目录迭代器返回的。

【讨论】:

    【解决方案2】:

    此函数将文件夹收集到给定的向量中。如果您将 recursive 设置为 true,它将扫描文件夹内文件夹内的文件夹等。

    // TODO: proper error handling.
    
    void GetFolders( std::vector<std::wstring>& result, const wchar_t* path, bool recursive )
    {
        HANDLE hFind;
        WIN32_FIND_DATA data;
        std::wstring folder( path );
        folder += L"\\";
        std::wstring mask( folder );
        mask += L"*.*";
    
        hFind=FindFirstFile(mask.c_str(),&data);
        if(hFind!=INVALID_HANDLE_VALUE)
        {
            do
            {
                std::wstring    name( folder );
                name += data.cFileName;
                if ( ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
                     // I see you don't want FILE_ATTRIBUTE_REPARSE_POINT
                     && !( data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) )
                {
                    // Skip . and .. pseudo folders.
                    if ( wcscmp( data.cFileName, L"." ) != 0 && wcscmp( data.cFileName, L".." ) != 0 )
                    {
                        result.push_back( name );
                        if ( recursive )
                            // TODO: It would be wise to check for cycles!
                            GetFolders( result, name.c_str(), recursive );
                    }
                }
            } while(FindNextFile(hFind,&data));
        }
        FindClose(hFind);
    }
    

    修改自https://stackoverflow.com/a/46511952/8666197

    【讨论】:

      猜你喜欢
      • 2012-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-27
      相关资源
      最近更新 更多