代码之家  ›  专栏  ›  技术社区  ›  Arshdeep

如何找到大文件的CRC32?

  •  4
  • Arshdeep  · 技术社区  · 16 年前

    PHP的CRC32支持将字符串作为输入。对于一个文件,下面的代码将用于ofc。

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

    但如果文件变大(2GB),可能会引发内存不足的致命错误。

    有没有办法找到大文件的校验和?

    3 回复  |  直到 14 年前
        1
  •  0
  •   NullUserException Mark Roddy    14 年前

    This function 在用户贡献的笔记中 crc32() 声明在不完全加载文件的情况下计算该值。如果它工作正常,应该可以消除任何内存问题。

    但是,对于大于2GB的文件,它可能会在当前遇到的相同32位限制处停止。

    如果可能的话,我将调用一个外部工具,它可以计算与现有文件一样大的文件的校验和。

        2
  •  5
  •   dev-null-dweller    16 年前

    PHP不支持大于2GB的文件(32位限制)

    以及从文件计算CRC32的更有效方法:

    $hash = hash_file('crc32b',"myfile.CSV" );
    
        3
  •  0
  •   Maxime Pacary    14 年前

    dev空居民 我的回答是我该走了。

    然而,对于那些正在寻找一个记忆效率高的php4反向端口的人来说, hash_file('crc32b', $filename); ,这里有一个基于 this PHP manual comment ,有一些改进:

    • 现在的结果与 hash_file()
    • 它支持32位和64位体系结构。

    警告: 表演很难看。努力改进。

    注意:我尝试过一种基于zaf注释中的C源代码的解决方案,但是我不能很快成功地将其移植到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);
        }
    }