如何快速枚举Win32上的目录? 我试图加快C++中的目录枚举,在这里我递归到子目录中。我目前有一个应用程序,它将95%的时间花在FindFirst/FindNextFile API上,枚举给定卷上的所有文件需要几分钟。我知道这样做可能更快,因为有一个应用程序可以:。它以秒为单位枚举我的整个驱动器

如何快速枚举Win32上的目录? 我试图加快C++中的目录枚举,在这里我递归到子目录中。我目前有一个应用程序,它将95%的时间花在FindFirst/FindNextFile API上,枚举给定卷上的所有文件需要几分钟。我知道这样做可能更快,因为有一个应用程序可以:。它以秒为单位枚举我的整个驱动器,c++,winapi,C++,Winapi,我怎样才能完成这样的事情呢?不要立即递归,保存找到的目录列表,完成后再深入目录。您希望对每个目录进行线性访问,以利用引用的位置和操作系统正在进行的任何缓存。“Everything”在后台构建索引,因此查询针对的是索引而不是文件系统本身 有一些改进需要做-至少在直接算法上: 首先,广度搜索优于深度搜索。也就是说,在递归到找到的子文件夹之前,枚举并处理单个文件夹中的所有文件。这改善了地方性——通常是很多 在Windows 7/W2K8R2上,您可以将FindFirstFileEx与FindExInf

我怎样才能完成这样的事情呢?

不要立即递归,保存找到的目录列表,完成后再深入目录。您希望对每个目录进行线性访问,以利用引用的位置和操作系统正在进行的任何缓存。

“Everything”在后台构建索引,因此查询针对的是索引而不是文件系统本身

有一些改进需要做-至少在直接算法上:

首先,广度搜索优于深度搜索。也就是说,在递归到找到的子文件夹之前,枚举并处理单个文件夹中的所有文件。这改善了地方性——通常是很多

在Windows 7/W2K8R2上,您可以将
FindFirstFileEx
FindExInfoBasic
一起使用,主要的加速功能是在启用此功能的NTFS文件系统上省略短文件名

如果枚举不同的物理磁盘(不仅仅是驱动器),则单独的线程会有所帮助。对于同一个磁盘,只有当它是SSD(“零寻道时间”)或您花费大量时间处理文件名(与磁盘访问时间相比)时,它才有帮助


[edit]实际上有一些评论- 基本上,他们跳过了文件系统抽象层,直接访问NTFS。通过这种方式,他们可以批量调用并跳过文件系统的昂贵服务,例如检查ACL

一个好的起点是MSDN上的。与Win32 FindFirst/FindNext API相比,“Everything”访问目录信息的级别更低

我相信它直接读取和解释NTFS MFT结构,这是其性能的主要原因之一。这也是为什么它需要管理员权限,以及为什么“一切”只索引本地或可移动NTFS卷(例如,不是网络驱动器)

执行类似操作的其他几个实用程序包括:

  • 借着我的权利火花

在这些工具上使用调试器进行一点反向工程可能会让您对它们使用的技术有一些了解。

如果您已经尽了最大努力从API中获得最大速度,那么下一步就是执行低级磁盘访问并完全绕过窗口。您可能会从中得到一些指导,或者您可以直接使用。

我知道这是一篇老文章,但是source forge上有一个项目,它完全按照您的要求进行,并且源代码是可用的


您可以在此处找到该项目:

如果您是在NTFS上执行此操作,则这里有一个用于低级别访问的库:

您可以枚举$MFT中的所有文件记录,每个记录表示磁盘上的一个真实文件。您可以从记录中获取所有文件属性,包括$DATA


这可能是枚举NTFS卷上所有文件/目录的最快方法,在我测试时,每分钟可枚举200k~300k文件。

也许我对它的读取太多,但此行“Everything”要求对卷和此行“Everything”进行低级别读取访问的管理权限只在本地NTFS卷上定位文件和文件夹会使我相信它正在使用内核模式API调用来完成它的工作,或者可能直接与文件系统驱动程序接口。@slugster:是的,可能是这样+1问题是,我如何做到这一点?作为一个有根据的猜测,我会说他们可能正在使用过滤器驱动程序。我可能真的下载了它,并有一个发挥。我注意到他们没有提到Win7,这可能会进一步加重我的猜测,因为Vista的驱动程序模型有所改变,然后又是Win7。@slugster:我可以确认它没有使用驱动程序,在Win7上运行得很好。@Billy:当然,从索引读取会更快,但他们如何构建/更新该索引呢?他们是在捏造他们声称的时间,还是在做一些特殊的事情?NTFS更改日志有助于使索引保持最新。@Ben Voigt:是的,但是如果我删除更改日志和所有缓存,开始时间仍然不到一分钟@彼得森:一切都在Windows XP上运行,所以我不认为新的Windows 7 API是它速度快的原因。@彼得森你需要把你的编辑放在这个答案的顶部。这是加速的根本原因。“使用调试器进行一点反向工程”@BillyONeal:我能理解这两点。顺便说一下,您不必钻研汇编语言来获取信息。像Dependency Walker()和Process Monitor()这样的工具可以告诉您很多关于程序使用的api的信息,而无需一直潜入反汇编。使用这些工具是否会违反EULA是我不能告诉你的。我想这应该是答案。GPL虽然:(不是这个项目的选项,因为它使用自由许可证(即Boost软件许可证;尽管我正在考虑切换到2条款BSD…)@BillyONeal:很明显,这个库现在是在BSD许可下的。但我确实记得,在我自己的项目中,因为我是GPL,所以我不把它作为一个选择。