Php 你能把一个文件散列到一定的长度吗

Php 你能把一个文件散列到一定的长度吗,php,hash,sha,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

我需要比较两个文件。一个文件可能比另一个文件长,我需要检查较长的文件是否包含较短文件的所有数据。 我可以对这两个进行二进制比较,如下所示:

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;
}
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;
}
A.txt: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

B.txt: AAAAAAAAAAAAAAAAAAAAABBBBBBBBBB

Stream ---------------------^
Result ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓X
但这将是缓慢的。作为替代方案,我可以将较小文件的SHA1哈希与较大文件的SHA1哈希进行比较,直到较小文件的大小,如下所示:

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;
}
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;
}
A.txt: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

B.txt: AAAAAAAAAAAAAAAAAAAAABBBBBBBBBB

Stream ---------------------^
Result ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓X
函数比较文件($file\u a,$file\b){
$tmpfile='/dev/shm/tmp_file_copy.bin';
如果(文件大小($file_a)>文件大小($file_b)){
$readfromfile=$file\u b;
$bytes\u to\u copy=文件大小($file\b);
}否则{
$readfromfile=$file\u a
$bytes\u to\u copy=文件大小($file\u a);
}
$readfile=fopen($readfromfile,'rb');
$writefile=fopen($tmpfile,'wb');
而(!feof($readfile)&&$bytes\u to\u copy>0){

如果($BythytoToopReope)字节是最好的方法,在它的情况下,它只比较两个文件的第一个X字节和不同的停止。哈希函数必须处理文件中的所有字节。这不是那么慢吗?< /p> 在这种情况下散列文件只会慢一些。考虑下面的情况。 文件
A.txt
内容:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAABBBBBBBBBB
文件
B.txt
内容:

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

我们需要对每个文件执行多少I/O才能确定
A.txt
是否包含所有
B.txt
?40个字节?30个字节?不,答案只有20个字节,因为这是两个文件共享的共同点。将每个文件流化一个字节(或字节块)每次比较一次,并在进行时进行比较。这种比较的结果如下所示:

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;
}
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;
}
A.txt: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

B.txt: AAAAAAAAAAAAAAAAAAAAABBBBBBBBBB

Stream ---------------------^
Result ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓X
然后你停下来,为什么要比较其他的呢


如果对两个文件进行散列,则必须在内存中保存全部内容才能计算散列。即使在将它们流式传输到内存时将它们散列成块,您认为哪个更快:比较每个文件中的每个字节还是对块进行散列?比较的复杂性是
O(字节数)
虽然SHA-1哈希算法的复杂性由指定。

比较所需的输出是什么?输出是真还是假。文件的内容与较短文件的长度匹配,或者不匹配。您可以使用fread将整个文件的字节X进行比较,您不需要在chunksYes中循环它,但是在我看来,分块更安全。我也可以在其中添加重试,但这会使问题变得更复杂,并从问题的角度误导读者。是的,我同意compareFiles会更有效,因为它会在达到较小文件的文件大小或他不同意。谢谢!:)很高兴你喜欢这个答案@Greg。如果你满意,请按绿色复选标记接受。