2010-06-05 18 views
4

La chaîne de support crc32 de PHP en entrée. Et Pour un fichier, le code ci-dessous fonctionnera OFC.Comment trouver crc32 de gros fichiers?

crc32(file_get_contents("myfile.CSV")); 

Mais si le fichier devient énorme (2 Go), il peut augmenter la mémoire. Erreur fatale.

Donc, n'importe quel moyen de trouver la somme de contrôle des fichiers volumineux?

Répondre

0

This function dans les Notes d'apport de l'utilisateur à crc32() réclamations pour calculer la valeur sans charger le fichier dans son intégralité. Si cela fonctionne correctement, cela devrait éliminer tous les problèmes de mémoire.

Pour un fichier de plus de 2 Go, il est probable qu'il s'arrête à la même limite de 32 bits que celle que vous êtes en train de rencontrer.

Si possible, je voudrais appeler un outil externe qui peut calculer la somme de contrôle pour les fichiers aussi grands que celui à portée de main.

+0

Vous connaissez un outil externe qui va calculer crc32? Je suis sur Linux (Debian Flavor.) – Arshdeep

+3

Le code source pour un ici: http://www.csbruce.com/~csbruce/software/crc32.c – zaf

+3

@zaf - Travaillé awesomely Vous êtes un ** STAR ** – Arshdeep

5

PHP ne supporte pas les fichiers de plus de 2 Go (limitation 32bit)

et le mode de calcul CRC32 à partir de fichiers plus efficace:

$hash = hash_file('crc32b',"myfile.CSV"); 
+0

Oh ok vous avez modifié, Merci pour ce copain :) une fois de plus modifié – Arshdeep

+0

- 'crc32b' est algorithme de hachage correct pour la plupart des cas. –

0

dev-null-dweller La réponse de est OMI la voie à suivre.

Cependant, pour ceux qui sont à la recherche d'un backport PHP4 économe en mémoire de hash_file('crc32b', $filename);, voici une solution basée sur this PHP manual comment, avec quelques améliorations:

  • Il donne maintenant exactement les mêmes résultats que hash_file()
  • Il prend en charge 32 bits & architectures 64 bits.

Avertissement: Les symboles sont moche. Essayer d'améliorer.

Note: J'ai essayé une solution basée sur le code source C du commentaire de zaf, mais je n'ai pas réussi assez rapidement à le porter sur PHP.

if (!function_exists('hash_file')) 
{ 
    define('CRC_BUFFER_SIZE', 8192); 

    function hash_file($algo, $filename, $rawOutput = false) 
    { 
     $mask32bit = 0xffffffff; 

     if ($algo !== 'crc32b') 
     { 
      trigger_error("Unsupported hashing algorightm '".$algo."'", E_USER_ERROR); 
      exit; 
     } 

     $fp = fopen($filename, 'rb'); 

     if ($fp === false) 
     { 
      trigger_error("Could not open file '".$filename."' for reading.", E_USER_ERROR); 
      exit; 
     } 

     static $CRC32Table, $Reflect8Table; 
     if (!isset($CRC32Table)) 
     { 
      $Polynomial = 0x04c11db7; 
      $topBit = 1 << 31; 

      for($i = 0; $i < 256; $i++) 
      { 
       $remainder = $i << 24; 
       for ($j = 0; $j < 8; $j++) 
       { 
        if ($remainder & $topBit) 
         $remainder = ($remainder << 1)^$Polynomial; 
        else 
         $remainder = $remainder << 1; 

        $remainder &= $mask32bit; 
       } 

       $CRC32Table[$i] = $remainder; 

       if (isset($Reflect8Table[$i])) 
        continue; 
       $str = str_pad(decbin($i), 8, '0', STR_PAD_LEFT); 
       $num = bindec(strrev($str)); 
       $Reflect8Table[$i] = $num; 
       $Reflect8Table[$num] = $i; 
      } 
     } 

     $remainder = 0xffffffff; 
     while (!feof($fp)) 
     { 
      $data = fread($fp, CRC_BUFFER_SIZE); 
      $len = strlen($data); 
      for ($i = 0; $i < $len; $i++) 
      { 
       $byte = $Reflect8Table[ord($data[$i])]; 
       $index = (($remainder >> 24) & 0xff)^$byte; 
       $crc = $CRC32Table[$index]; 
       $remainder = (($remainder << 8)^$crc) & $mask32bit; 
      } 
     } 

     $str = decbin($remainder); 
     $str = str_pad($str, 32, '0', STR_PAD_LEFT); 
     $remainder = bindec(strrev($str)); 
     $result = $remainder^0xffffffff; 
     return $rawOutput ? strrev(pack('V', $result)) : dechex($result); 
    } 
} 
+0

Ceci est intéressant. Je suppose qu'il devrait y avoir un moyen de hacher un fichier par bloc en utilisant la méthode native crc32(). Je me souviens d'implémenter une fonction crc16 (il y a longtemps), que crc16 (data.crc16 (data)) == 0x0000. S'il y a un moyen de deviner quelles sont les données à ajouter au prochain bloc afin d'obtenir le crc32 du dernier bloc, vous pouvez y aller. En d'autres termes, si vous pouvez calculer efficacement une valeur de 32 bits x à partir de crc32 (block1) tel que crc32 (x) = crc32 (block1), alors crc32 (block1.block2) = crc32 (x.block2). Quelqu'un a une idée si cela serait faisable? –

+0

Encore mieux, j'ai trouvé [ce post] (http://php.net/manual/fr/function.crc32.php#100060) qui laisse penser que vous pouvez trouver une fonction crc32_combine() telle que crc32_combine (crc32 (bloc1), crc32 (bloc2)) = crc32 (bloc1.block2). Malheureusement, le message original auquel il fait référence est parti!Open source Zlib a une implémentation de crc32_combine() que nous pourrions jeter un coup d'oeil, cependant. Je vais essayer de creuser ça. –