高效地列出目录中的所有子目录

6
请看已经采纳的建议:
我正在尝试使用WinAPI和C ++列出给定目录中的所有目录(文件夹)。
目前,我的算法速度慢且效率低下: - 使用FindFirstFileEx()打开要搜索的文件夹 - 然后查看目录中的每个文件(使用FindNextFile()),如果它是目录文件,则将其绝对路径存储在向量中,如果只是文件,则不执行任何操作。
这似乎非常低效,因为我正在查看目录中的每个文件。
以下是需要回答的问题: 1. 是否有WinAPI函数可以告诉我给定目录中的所有子目录? 2. 您是否知道我可以使用哪种算法来有效地定位和识别目录(文件夹)?
编辑: 所以在采纳了建议之后,我使用了FindExSearchLimitToDirectories进行搜索,但对我来说它仍然会打印出所有文件(.txt等),而不仅仅是文件夹。我做错了什么吗?
WIN32_FIND_DATA dirData;
HANDLE dir = FindFirstFileEx( "c:/users/soribo/desktop\\*", FindExInfoStandard, &dirData, 
                              FindExSearchLimitToDirectories, NULL, 0 );

while ( FindNextFile( dir, &dirData ) != 0 )
{
    printf( "FileName: %s\n", dirData.cFileName );
}
2个回答

2
为了获得性能提升,必须在文件系统级别上提供支持。如果没有此支持,则系统必须枚举目录中的每个对象。
原则上,您可以使用FindFirstFileEx指定FindExSearchLimitToDirectories标志。但是,文档指出(重点是我的):
“这是一个建议性标志。如果文件系统支持目录过滤,则函数将搜索与指定名称匹配并且也是目录的文件。如果文件系统不支持目录过滤,则此标志被静默忽略。 如果需要目录筛选,则可以在所有文件系统上使用此标志,但由于它是一个建议性标志,并且仅影响支持它的文件系统,因此应用程序必须检查存储在FindFirstFileEx函数的lpFindFileData参数中的文件属性数据,以确定函数是否返回句柄到目录。”
然而,据我所知,信息很少,在桌面文件系统上不广泛支持FindExSearchLimitToDirectories标志。
你最好使用FindFirstFileExFindExSearchLimitToDirectories。你仍然需要自己进行过滤,以防你遇到一个不支持文件系统级别目录过滤的文件系统。如果你运气好并碰到支持它的文件系统,则会获得性能优势。

1
如果您正在使用FindFirstFileEx,那么您应该能够指定_FINDEX_SEARCH_OPS::FindExSearchLimitToDirectories选项(用作FindFirstFileEx中的fSearchOp参数),以限制第一次搜索(和任何后续的FindNextFile())调用到目录。

FindExSearchLimitToDirectories非常复杂,值得在您的答案中指出一些复杂性。此外,我不确定它是否会导致枚举速度显著加快。过滤是在文件系统级别完成的吗? - David Heffernan
根据MSDN的说法,“如果文件系统支持目录过滤,则该函数将搜索具有指定名称的目录。”,因此我认为它是在文件系统级别进行过滤。我不确定性能影响 - 我无法对其进行分析,因为我家里没有Windows机器。 - Demian Brecht
谢谢回复,请看我的编辑,您的方法还不太起作用。 - user593747
3
FindExSearchLimitToDirectories仅提供建议作用,因此不能保证只返回目录;它只是在支持该功能的文件系统上启用了一种优化。 - Gabe
很奇怪,我有Windows 7,而且我一年前就买了这台笔记本电脑,优化会在上面吗?也许我需要以某种方式启用它? - user593747
@user:我认为这种优化是针对网络文件服务器的,我怀疑你在本地看不到它。 - Gabe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接