1

我手头有一项(看起来像是)一项大任务。
我需要浏览多个文件夹的不同归档卷(我们说的是 TB 级数据)。每个文件夹中都有一个 .pst 文件。其中一些文件夹(以及文件)可能完全相同(文件中的名称或数据)。我希望能够一次比较两个以上的文件(如果可能的话),看看是否找到了任何重复文件。找到重复项后,我需要删除它们并保留原件,然后最终提取所有唯一的电子邮件。

我知道有些程序可以找到重复项,但我不确定他们需要在这些文件中传递什么参数,我不知道他们是否可以处理如此大量的数据。我想用 C# 或 VB 编程。我不知道应该从哪里开始。有什么建议么??

前任...

m:\mail\name1\name.pst

m:\mail\name2\name.pst (same exact data as the one above)

m:\mail\name3\anothername.pst (duplicate file to the other 2)
4

2 回答 2

1

我将通过首先递归查找所有 PST 文件,然后匹配文件长度,然后按固定的字节前缀过滤,最后执行完整的哈希或字节比较以获得实际匹配来完成查找重复项的过程。

递归地构建列表并找到潜在的匹配项可以像这样简单:

Func<DirectoryInfo, IEnumerable<FileInfo>> recurse = null;
recurse = di => di.GetFiles("*.pst")
    .Concat(di.GetDirectories()
        .SelectMany(cdi => recurse(cdi)));

var potentialMatches =
    recurse(new DirectoryInfo(@"m:\mail"))
        .ToLookup(fi => fi.Length)
        .Where(x => x.Skip(1).Any());

potentialMatches查询按文件大小为您提供了一系列完整的潜在匹配项。

然后,我将使用以下函数(我将实现留给您)进一步过滤此列表。

Func<FileInfo, FileInfo, int, bool> prefixBytesMatch = /* your implementation */
Func<FileInfo, FileInfo, bool> hashMatch = /* your implementation */

通过文件长度和字节前缀限制匹配,您将显着减少超大文件所需的哈希计算。

我希望这有帮助。

于 2012-10-19T01:40:15.707 回答
1

如果您只想删除整个重复文件,则该任务很容易实现。

您将必须浏览所有文件夹并对每个文件的内容进行哈希处理。产生的散列有一些位(例如 32 到 256 位)。如果两个文件哈希值相等,则各个文件相同的概率极高(取决于哈希函数的抗碰撞性,读取的位数)。

当然,现在实现取决于您(我不是 C# 或 VB 程序员),但我建议您使用类似以下伪代码的内容(接下来我会解释每个步骤并为您提供演示如何在 C# 中执行此操作的链接) :

    do{
       file_byte_array = get_file_contents_into_byte_array(file)          1
       hash = get_hash from_byte_array(file_byte_array);                  2
       if(hashtable_has_elem(hashtable,hash))                             3
         remove_file(file);                                               4
       else                                                               5
         hashtable_insert_elem(hashtable,hash,file);                      6
     }while_there_are_files_to evaluate                                   7

此逻辑应在所有.pst文件上执行。在第 1 行(我假设您打开了文件),您将文件的所有内容写入字节数组。

获得文件的字节数组后,必须使用散列函数(第 2 行)对其进行散列。您有大量的哈希函数实现可供选择。在某些实现中,您必须将文件分成块并散列每个块的内容(例如hereherehere)。如果您的文件真的很大并且不适合您的记忆,那么将文件分成几部分可能是唯一的选择。另一方面,您有许多接受整个流的函数(例如,这里这里是与您的问题非常相似的示例这里这里,但我建议您使用超快的MurmurHash3)。如果您有效率要求,请远离加密哈希函数,因为它们要重得多,并且您不需要加密属性来执行任务。

最后,在计算完散列之后,您只需要获取一些保存散列并比较它们的方法,以便找到相同的散列(读取文件)并删除它们(第 3-6 行)。我打算使用哈希表字典,其中标识符(用于执行查找的对象)是文件哈希,对象 File 是条目值。

笔记:

记住!!!: 哈希值的位数越多,冲突的可能性就越小。如果您想了解更多关于散列函数中的碰撞概率的信息,请阅读这篇出色的文章。您必须注意此主题,因为您的目标是删除文件。如果发生冲突,那么您将删除一个不相同的文件,并且您将永远丢失它。有许多策略可以识别冲突,您可以将它们组合起来并添加到您的算法中(例如比较文件的大小、比较随机位置的文件内容值、使用多个哈希函数)。我的建议是使用所有这些策略。如果您使用两个散列函数,那么对于两个被认为相同的文件,它们的每个散列函数的散列值必须相等:

    file1, file2;
    file1_hash1  = hash_function1(file1);
    file2_hash1  = hash_function1(file2);
    file1_hash2  = hash_function2(file1);
    file2_hash2  = hash_function2(file2);

    if(file1_hash1 == file2_hash1 &&
       file2_hash2 == file2_hash2)
      // file1 is_duplicate_of file2;
    else
      // file1 is_NOT_duplicate_of file2;
于 2012-10-19T00:21:01.883 回答