你可以SHA1将文件哈希到一定长度

时间:2018-01-23 20:34:31

标签: php hash sha

我需要比较两个文件。一个文件可能比另一个文件长,我需要检查较长的文件是否包含较短文件的所有数据。 我可以做两个这样的二元比较:

function compareFiles($file_a, $file_b){
  if (filesize($file_a) > filesize($file_b)){
    $fp_a = fopen($file_b, 'rb');
    $fp_b = fopen($file_a, 'rb');
  } else { // filesize($file_b) > filesize($file_a)
    $fp_a = fopen($file_a, 'rb');
    $fp_b = fopen($file_b, 'rb');
  }
  while (($b = fread($fp_a, 4096)) !== false){
    $b_b = fread($fp_b, 4096);
    if ($b !== $b_b){
      fclose($fp_a);
      fclose($fp_b);
      return false;
    }
  }
  fclose($fp_a);
  fclose($fp_b);
  return true;
}

但这会很慢。作为替代方案,我可以将较小文件的SHA1哈希值与较大文件的SHA1哈希值进行比较,直到较小文件的大小为止,如下所示:

function compareFiles($file_a, $file_b){
  $tmpfile = '/dev/shm/tmp_file_copy.bin';
  if (filesize($file_a) > filesize($file_b)){
    $readfromfile = $file_b;
    $bytes_to_copy = filesize($file_b);
  } else {
    $readfromfile = $file_a
    $bytes_to_copy = filesize($file_a);
  }
  $readfile = fopen($readfromfile, 'rb');
  $writefile = fopen($tmpfile, 'wb');
  while (!feof($readfile) && $bytes_to_copy> 0) {
    if ($bytes_to_copy <= 8192) {
      $contents = fread($readfile, $bytes_to_copy);
      $bytes_to_copy = 0;
    } else {
      $contents = fread($readfile, 8192);
      $bytes_to_copy =- 8192;
    }
    fwrite($writefile, $contents);
  }
  fclose($writefile);
  fclose($readfile);
  $result = sha1_file($readfromfile = $file_a ? $file_b : $file_a) === sha1_file($tmpfile);
  unlink($tmpfile);
  return $result;
}

但我担心这也会很慢,因为它涉及很多I / O(到/ dev / shm)。

简而言之,我正在寻找一种更好的方式......

2 个答案:

答案 0 :(得分:2)

在这种情况下散列文件的速度会慢一些。请考虑以下情况。

档案A.txt内容:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

档案B.txt内容:

AAAAAAAAAAAAAAAAAAAAABBBBBBBBBB

请注意,A.txt总共40个字符,比30个字符的B.txt长10个字符

我们必须对每个文件执行多少I / O以确定A.txt是否包含B.txt的所有内容? 40个字节? 30个字节?不,答案只有20个字节,因为这是两个文件共享的共同点。您可以一次将每个文件流式传输一个字节(或一块字节),并随时进行比较。这种比较的结果如下:

A.txt: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

B.txt: AAAAAAAAAAAAAAAAAAAAABBBBBBBBBB

Stream ---------------------^
Result ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓X

然后你停下来。为什么要比较其余的?

如果您对两个文件进行散列,则必须将所有内容都放在内存中以计算散列值。即使你将它们分块并将它们分流到内存中,你认为哪个更快:比较每个文件的每个字节或散列块?比较的复杂性为O(number of bytes),而SHA-1哈希算法的复杂性由RFC 3174指定。

答案 1 :(得分:1)

逐字节是您的最佳方法。它只比较两个文件的第一个 x 字节,如果它们不同则停止。散列函数必须处理文件中的所有字节。那不是更慢吗?