在C ++中查找重复文件的最佳方法是什么?

时间:2012-08-01 13:33:10

标签: c++ algorithm file

我想在C ++中找到文件系统上的重复文件。有没有算法尽快做到这一点?我是否需要创建一个多线程应用程序,或者我只能使用一个线程来完成它?

3 个答案:

答案 0 :(得分:10)

我同意Kerrek SB的说法,有比C ++更好的工具,但是,假设你真的需要在C ++中这样做,这里有一些建议和要在你的实现中考虑的事项:

  1. 使用boost :: filesystem进行可移植文件系统遍历

  2. 散列每个文件建议都非常合理,但首先制作文件大小为关键的多重映射可能更有效。然后仅在存在重复大小的文件时应用哈希。

  3. 决定如何处理空文件和符号链接/捷径

  4. 决定了您希望如何处理特殊文件,例如:在unix上你有目录fifos,socket等

  5. 说明在算法运行时文件或目录结构可能会发生变化,消失或移动的事实

  6. 说明某些文件或目录可能无法访问或损坏(例如递归目录链接)

  7. 使线程数可配置为有意义的并行化数量取决于底层磁盘硬件和配置。如果你是一个简单的硬盘驱动器而不是昂贵的san,那将会有所不同。但是,不要做出假设;测试一下。例如,Linux非常适合缓存文件,因此很多读取都来自内存,因此不会阻塞i / o。

答案 1 :(得分:8)

1)不要使用C ++。您需要的所有工具都已存在。

2)散列每个文件(例如使用md5sum)并构建文件名,文件大小和哈希值的索引。*

3)按哈希值排序并查找重复的哈希值和大小对(例如,使用sort)。

4)对候选人重复做一个普通的diff

您可以通过一些工作来并行化步骤2),但您将受到存储的I / O速度的限制。您可以通过将大型索引文件拆分为位,对它们进行单独排序然后合并它们来并行化步骤3)(<{1}})。

*)正如@frankc所说,实际上不要散列每个文件,而只是那些大小不唯一的文件。从基于 size 的索引开始。你需要散列很多小文件,但只有很少的大文件。

答案 2 :(得分:4)

我会这样做:

  • 扫描您感兴趣的目录,查看每个文件的大小;将对文件大小/路径存储在multimap中,文件大小为索引;
  • 然后,每个键只用一个元素扫描multimap桶,即大小唯一的文件;那些肯定不能重复。
  • 对剩余文件的内容进行哈希处理,并执行与以前相同的操作(multimap,其中哈希为键,路径为值)。
  • 然后仅对具有相同散列的文件执行实际(每字节字节)比较。

这个过程应该比盲目地散列所有文件快得多,因为大多数文件都有不同的大小,只要看一下就可以分开;并且检查文件大小比散列文件便宜得多,因为它只是一个文件系统属性查找而不是读取文件的整个内容。

需要最后一步,因为可能存在具有相同散列的不同文件;但是由于具有良好的散列函数,大部分工作已经完成,因为不相关文件的散列冲突应该非常少见。

请注意,您的哈希函数不需要加密安全,也不需要特别快(我想这个过程的时间将由IO控制)。

此外,由于您实际上不需要有一个已排序的容器,而不是multimap,您可以使用unordered_multimap,因为它应该有更快的查找时间,一旦您知道有多少您必须处理的文件,您可以使用明确的最大元素数调用reserve,避免重新分配。