从文件

时间:2018-01-16 07:40:51

标签: java file hash

TL; DR:如何从一个大的文件中识别重复的非重叠1kb块,也可以是二进制文件?
我最近在其中一个挑战中遇到了这个问题。
我们有一个文件名。该文件的大小将是1kb的倍数。我们必须对此文件执行重复数据删除操作,并将修改后的内容写入另一个文件。重复数据删除操作从文件中查找并删除重复的,非重叠的1kb块。该文件可以是非常大的文件,也可以是二进制文件。
问题的第二部分涉及逆转重复数据删除操作并从重复数据删除的文件中重新生成原始文件。


我的方法:我尝试按照Adam Horwath的this博客中的建议使用哈希。我计算了每个1kb字节数据的散列,并将其存储在散列表中,散列作为键,并将块的索引作为值考虑。这是我的代码来计算1kb数据的哈希值(类似于博客中的inithash):

//implement hashing used in Rabin-Karp algorithm 
// sum of p^n * a[x]
//hconst = 69069; //good multiplier for mod 2^32;
 public static long  calculateHash(int [] data, int chunkSize){
    long hash = 1;
    for(int i =0; i < chunkSize; i++)
    {
        int c = data[i];
        hash *= hconst; //multiply with const
        hash += c; //add the byte to hash
    }
    return hash;    
}

我的理解或实施有一些错误(显然),它没有给出正确的结果。我的问题是:

  • 哈希方法是否正确以识别重复的块?(比较每个字节是一个代价高昂的过程)
  • 有没有更好的方法来识别重复的块?

1 个答案:

答案 0 :(得分:0)

有比内核内哈希表更好的方法吗?是。尤其是如果输入文件大于RAM。

您解释说,您拥有大量的1 KiB文档,大量的文件段。通过读取每个段并将每个段写一行到包含两列的临时segments.txt文件中进行预处理。第一列具有段内容或SHA224内容哈希的副本。第二列具有段索引号,它是从零开始的序列号。可以随意使用哈希的前几个字节,具体取决于您对哈希冲突的敏感程度。

现在使用/usr/bin/sort(核心外合并排序)创建segments_sorted.txt。在这一点上,您的问题微不足道。简单地阅读每一行,同时记住先前的哈希。如果cur_hash == prev_hash,那么您已识别出重复的块。关联的索引使您可以快速seek()查找原始内容,以防潜在的冲突对您的应用程序很重要。