Как найти crc32 больших файлов? - PullRequest
4 голосов
/ 05 июня 2010

Строка PHP поддержки crc32 в качестве входных данных. И для файла, приведенный ниже код будет работать OFC.

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

Но если размер файла увеличивается (2 ГБ), это может привести к нехватке памяти. Неустранимая ошибка.

Так есть ли способ найти контрольную сумму огромных файлов?

Ответы [ 3 ]

5 голосов
/ 05 июня 2010

PHP не поддерживает файлы размером более 2 ГБ (ограничение 32 бита)

И более эффективный способ вычисления crc32 из файлов:

$hash = hash_file('crc32b',"myfile.CSV" );
0 голосов
/ 08 декабря 2011

dev-null-dweller ответ ИМО - путь.

Тем не менее, для тех, кто ищет резервный порт PHP4 с эффективным использованием памяти hash_file('crc32b', $filename);, вот решение, основанное на этом комментарии к PHP-руководству с некоторыми улучшениями:

  • Теперь он дает те же результаты, что и hash_file()
  • Он поддерживает 32-битные и 64-битные архитектуры.

Предупреждение: ужасны. Пытаюсь улучшить.

Примечание. Я попробовал решение, основанное на исходном коде C, из комментария zaf, но не смог достаточно быстро перенести его на 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 голосов
/ 05 июня 2010

Эта функция в комментариях пользователя к crc32() утверждает, что вычисляет значение без полной загрузки файла. Если он работает правильно, он должен устранить любые проблемы с памятью.

Для файла размером более 2 ГБ он, вероятно, остановится на том же 32-разрядном ограничении, с которым вы столкнулись прямо сейчас.

Если возможно, я бы вызвал внешний инструмент, который может вычислить контрольную сумму для файлов размером с тот, который находится под рукой.

...