質問
PHPのCRC32は入力として文字列をサポートします。
crc32(file_get_contents("myfile.CSV"));
しかし、ファイルが巨大になった場合(2 GB)、メモリから致命的なエラーを引き起こす可能性があります。
それで、巨大なファイルのチェックサムを見つける方法はありますか?
解決
この機能 ユーザーに注目を集めました crc32()
ファイルを完全にロードせずに値を計算すると主張します。正しく動作する場合、メモリの問題を排除する必要があります。
ただし、2 GBを超えるファイルの場合、現在遭遇しているのと同じ32ビット制限で停止する可能性があります。
可能であれば、手元のファイルと同じ大きさのファイルのチェックサムを計算できる外部ツールを呼び出します。
他のヒント
PHPは2GBを超えるファイルをサポートしていません(32ビット制限)
ファイルからCRC32を計算するより効率的な方法:
$hash = hash_file('crc32b',"myfile.CSV" );
dev-null-dwellerの答えはIMOです。
ただし、メモリ効率の高いPHP4バックポートを探している人のために hash_file('crc32b', $filename);
, 、ここに基づいたソリューションがあります このPHPマニュアルコメント, 、いくつかの改善があります:
- 現在、まったく同じ結果が得られます
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);
}
}
所属していません StackOverflow