字符串函数
在线手册:中文  英文

crc32

(PHP 4 >= 4.0.1, PHP 5)

crc32计算一个字符串的 crc32 多项式

说明

int crc32 ( string $str )

生成 str 的 32 位循环冗余校验码多项式。这通常用于检查传输的数据是否完整。

Warning

由于 PHP 的整数是带符号的,所以在 32 位系统上许多 crc32 校验码将返回负整数。 尽管在 64 位上所有 crc32() 的结果将都是正整数。

因此你需要使用 sprintf()printf() 的“%u”格式符来获取表示无符号 crc32 校验码的字符串。

For a hexadecimal representation of the checksum you can either use the "%x" formatter of sprintf() or printf() or the dechex() conversion functions, both of these also take care of converting the crc32() result to an unsigned integer.

Having 64bit installations also return negative integers for higher result values was considered but would break the hexadecimal conversion as negatives would get an extra 0xFFFFFFFF######## offset then. As hexadecimal representation seems to be the most common use case we decided to not break this even if it breaks direct decimal comparisons in about 50% of the cases when moving from 32 to 64bits.

In retrospect having the function return an integer maybe wasn't the best idea and returning a hex string representation right away (as e.g. md5() does) might have been a better plan to begin with.

For a more portable solution you may also consider the generic hash(). hash("crc32b", $str) will return the same string as dechex(crc32($str)).

参数

str

要校验的数据。

返回值

返回 str crc32 校验的整数。

范例

Example #1 显示一个 crc32 校验码

示例中的第二行演示了如何使用 printf() 函数转换校验码:

<?php
$checksum 
crc32("The quick brown fox jumped over the lazy dog.");
printf("%u\n"$checksum);
?>

参见


字符串函数
在线手册:中文  英文

用户评论:

D (2013-04-29 23:59:36)

<?php
$i 
crc32('weak_hash');
    
if(
$i // if hash is negative
{
        
$i*=-1// do some basic math
}

echo 
$i;

/*
OUTPUTS 275953381
*/
?>

JS at JavsSys dot Org (2013-04-13 16:22:06)

The khash() function by sukitsupaluk has two problems, it does not use all 62 characters from the $map set and when corrected it then produces different results on 64-bit compared to 32-bit PHP systems.

Here is my modified version :

<?php

/**
 * Small sample convert crc32 to character map
 * Based upon http://www.php.net/manual/en/function.crc32.php#105703
 * (Modified to now use all characters from $map)
 * (Modified to be 32-bit PHP safe)
 */
function khash($data)
{
    static 
$map "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
$hash bcadd(sprintf('%u',crc32($data)) , 0x100000000);
    
$str "";
    do
    {
        
$str $map[bcmod($hash62) ] . $str;
        
$hash bcdiv($hash62);
    }
    while (
$hash >= 1);
    return 
$str;
}
//-----------------------------------------------------------------------------------
$test = array(nulltruefalse0"0"1"1""2""3""ab""abc""abcd",
    
"abcde""abcdefoo""248840027""1365848013"// time()
    
"9223372035488927794"// PHP_INT_MAX-time()
    
"901131979"// mt_rand()
    
"Sat, 13 Apr 2013 10:13:33 +0000" // gmdate('r') 
);
$out = array();
foreach (
$test as $s)
{
    
$out[] = khash($s) . ": " $s;
}
print 
"<h3>khash() -- maps a crc32 result into a (62-character) result</h3>";
print 
'<pre>';
var_dump($out);
print 
"\n\n\$GLOBALS['raw_crc32']:\n";
var_dump($GLOBALS['raw_crc32']);
print 
'</pre><hr>';
flush();
$pefile __FILE__;
print 
"<h3>$pefile</h3>";
ob_end_flush();
flush();
highlight_file($pefile);
print 
"<hr>";
//-----------------------------------------------------------------------------------
/* CURRENT output
array(19) {
  [0]=>
  string(8) "4GFfc4: "
  [1]=>
  string(9) "76nO4L: 1"
  [2]=>
  string(8) "4GFfc4: "
  [3]=>
  string(9) "9aGcIp: 0"
  [4]=>
  string(9) "9aGcIp: 0"
  [5]=>
  string(9) "76nO4L: 1"
  [6]=>
  string(9) "76nO4L: 1"
  [7]=>
  string(9) "5b8iNn: 2"
  [8]=>
  string(9) "6HmfFN: 3"
  [9]=>
  string(10) "7ADPD7: ab"
  [10]=>
  string(11) "5F0aUq: abc"
  [11]=>
  string(12) "92kWw9: abcd"
  [12]=>
  string(13) "78hcpf: abcde"
  [13]=>
  string(16) "9eBVPB: abcdefoo"
  [14]=>
  string(17) "5TjOuZ: 248840027"
  [15]=>
  string(18) "5eNliI: 1365848013"
  [16]=>
  string(27) "4Q00e5: 9223372035488927794"
  [17]=>
  string(17) "6DUX8V: 901131979"
  [18]=>
  string(39) "5i2aOW: Sat, 13 Apr 2013 10:13:33 +0000"
}
*/
//-----------------------------------------------------------------------------------

?>

i at morfi dot ru (2013-03-18 13:16:33)

Implementation crc64() in php 64bit

<?php

/**
 * @return array
 */
function crc64Table()
{
    
$crc64tab = [];

    
// ECMA polynomial
    
$poly64rev = (0xC96C5795 << 32) | 0xD7870F42;

    
// ISO polynomial
    // $poly64rev = (0xD8 << 56);

    
for ($i 0$i 256$i++)
    {
        for (
$part $i$bit 0$bit 8$bit++) {
            if (
$part 1) {
                
$part = (($part >> 1) & ~(0x8 << 60)) ^ $poly64rev;
            } else {
                
$part = ($part >> 1) & ~(0x8 << 60);
            }
        }

       
$crc64tab[$i] = $part;
    }

    return 
$crc64tab;
}

/**
 * @param string $string
 * @param string $format
 * @return mixed
 * 
 * Formats:
 *  crc64('php'); // afe4e823e7cef190
 *  crc64('php', '0x%x'); // 0xafe4e823e7cef190
 *  crc64('php', '0x%X'); // 0xAFE4E823E7CEF190
 *  crc64('php', '%d'); // -5772233581471534704 signed int
 *  crc64('php', '%u'); // 12674510492238016912 unsigned int
 */
function crc64($string$format '%x')
{
    static 
$crc64tab;

    if (
$crc64tab === null) {
        
$crc64tab crc64Table();
    }

    
$crc 0;

    for (
$i 0$i strlen($string); $i++) {
        
$crc $crc64tab[($crc ord($string[$i])) & 0xff] ^ (($crc >> 8) & ~(0xff << 56));
    }

    return 
sprintf($format$crc);
}

Clifford dot ct at gmail dot com (2012-08-07 08:54:38)

The crc32() function can return a signed integer in certain environments. Assuming that it will always return an unsigned integer is not portable.
Depending on your desired behavior, you should probably use sprintf() on the result or the generic hash() instead. Also note that integer arithmetic operators do not have the precision to work correctly with the integer output.

alban dot lopez+php [ at ] gmail dot com (2011-11-26 18:02:42)

I made this code to verify Transmition with Vantage Pro2 ( weather station ) based on CRC16-CCITT standard.

<?php
// CRC16-CCITT validator
$crc_table = array(
    
0x0,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
        
0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
        
0x1231,  0x210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
        
0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
        
0x2462,  0x3443,  0x420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
        
0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
        
0x3653,  0x2672,  0x1611,  0x630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
        
0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
        
0x48c4,  0x58e5,  0x6886,  0x78a7,  0x840,  0x1861,  0x2802,  0x3823,
        
0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
        
0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0xa50,  0x3a33,  0x2a12,
        
0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
        
0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0xc60,  0x1c41,
        
0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
        
0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0xe70,
        
0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
        
0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
        
0x1080,  0xa1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
        
0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
        
0x2b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
        
0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
        
0x34e2,  0x24c3,  0x14a0,  0x481,  0x7466,  0x6447,  0x5424,  0x4405,
        
0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
        
0x26d3,  0x36f2,  0x691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
        
0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
        
0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x8e1,  0x3882,  0x28a3,
        
0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
        
0x4a75,  0x5a54,  0x6a37,  0x7a16,  0xaf1,  0x1ad0,  0x2ab3,  0x3a92,
        
0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
        
0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0xcc1,
        
0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
        
0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0xed1,  0x1ef0);

    
$test chr(0xC6).chr(0xCE).chr(0xA2).chr(0x03); // CRC16-CCITT = 0xE2B4
    
genCRC ($test);
       
function 
genCRC (&$ptr)
{
    
$crc 0x0000;
    
$crc_table $GLOBALS['crc_table'];
    for (
$i 0$i strlen($ptr); $i++)
        
$crc =  $crc_table[(($crc>>8) ^ ord($ptr[$i]))] ^ (($crc<<8) & 0x00FFFF);
    return 
$crc;
}
?>

arris at zsolttech dot com (2011-10-19 05:17:00)

not found anywhere crc64 based on http://bioinfadmin.cs.ucl.ac.uk/downloads/crc64/crc64.c .

(use gmp module)

<?php

/* OLDCRC */
define('POLY64REV'"d800000000000000");
define('INITIALCRC'"0000000000000000");
define('TABLELEN'256);
/* NEWCRC */
// define('POLY64REV', "95AC9329AC4BC9B5");
// define('INITIALCRC', "FFFFFFFFFFFFFFFF");

if(function_exists('gmp_init')){
        class 
CRC64{

                private static 
$CRCTable = array();

                public static function 
encode($seq){

                        
$crc gmp_init(INITIALCRC16);
                        
$init FALSE;
                        
$poly64rev gmp_init(POLY64REV16);

                        if (!
$init)
                        {
                                
$init TRUE;
                                for (
$i 0$i TABLELEN$i++)
                                {
                                        
$part gmp_init($i10);
                                        for (
$j 0$j 8$j++)
                                        {
                                                if (
gmp_strval(gmp_and($part"0x1")) != "0"){
                                                        
// if (gmp_testbit($part, 1)){ /* PHP 5 >= 5.3.0, untested */
                                                        
$part gmp_xor(gmp_div_q($part"2"), $poly64rev);
                                                } else {
                                                        
$part gmp_div_q($part"2");
                                                }
                                        }
                                        
self::$CRCTable[$i] = $part;
                                }
                        }

                        for(
$k 0$k strlen($seq); $k++){
                                
$tmp_gmp_val gmp_init(ord($seq[$k]), 10);
                                
$tableindex gmp_xor(gmp_and($crc"0xff"), $tmp_gmp_val);
                                
$crc gmp_div_q($crc"256");
                                
$crc gmp_xor($crcself::$CRCTable[gmp_strval($tableindex10)]);
                        }

                        
$res gmp_strval($crc16);

                        return 
$res;
                }
        }
} else {
        die(
"Please install php-gmp package!!!");
}
?>

sukitsupaluk at hotmail dot com (2011-09-08 03:04:25)

small sample convert crc32 to character map

<?php

function khash($data) {
    static 
$map="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
$hash=crc32($data)+0x100000000;
    
$str "";
    do {
        
$str $map[31+ ($hash 31)] . $str;
        
$hash /= 31;
    } while(
$hash >= 1);     
    return 
$str;
}
$test= array(null,TRUE,FALSE,0,"0",1,"1","2","3","ab","abc","abcd","abcde","abcdefoo");
$out = array();
foreach(
$test as $s)
{
    
$out[]=khash($s).": "$s;
}
var_dump($out);

/*
output:
array
  0 => string 'zVvOYTv: ' (length=9)
  1 => string 'xKDKKL8: 1' (length=10)
  2 => string 'zVvOYTv: ' (length=9)
  3 => string 'zOKCQxh: 0' (length=10)
  4 => string 'zOKCQxh: 0' (length=10)
  5 => string 'xKDKKL8: 1' (length=10)
  6 => string 'xKDKKL8: 1' (length=10)
  7 => string 'AFSzIAO: 2' (length=10)
  8 => string 'BXGSvQJ: 3' (length=10)
  9 => string 'xZWOQSu: ab' (length=11)
  10 => string 'AVAwHOR: abc' (length=12)
  11 => string 'zKASNE1: abcd' (length=13)
  12 => string 'xLCTOV7: abcde' (length=14)
  13 => string 'zQLzKMt: abcdefoo' (length=17)

*/

?>

chernyshevsky at hotmail dot com (2010-09-22 15:54:08)

The crc32_combine() function provided by petteri at qred dot fi has a bug that causes an infinite loop, a shift operation on a 32-bit signed int might never reach zero. Replacing the function gf2_matrix_times() with the following seems to fix it:

<?php
function gf2_matrix_times($mat$vec)
{
    
$sum=0;
    
$i=0;

    while (
$vec) {
        if (
$vec 1) {
            
$sum ^= $mat[$i];
        }
        
$vec = ($vec >> 1) & 0x7FFFFFFF;
        
$i++;       
    }
    return 
$sum;
}
?>

Otherwise, it's probably the best solution if you can't use hash_file(). Using a 1meg read buffer, the function only takes twice as long to process a 300meg files than hash_file() in my test.

gabri dot ns at gmail dot com (2010-09-15 22:05:28)

if you are looking for a fast function to hash a file, take a look at
http://www.php.net/manual/en/function.hash-file.php
this is crc32 file checker based on a CRC32 guide
it have performance at ~ 625 KB/s on my 2.2GHz Turion
far slower than hash_file('crc32b','filename.ext')
<?php
function crc32_file ($filename)
{
   
$f = @fopen($filename,'rb');
   if (!
$f) return false;
   
   static 
$CRC32Table$Reflect8Table;
   if (!isset(
$CRC32Table))
   {
      
$Polynomial 0x04c11db7;
      
$topBit << 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;
         }
         
         
$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 (
$data fread($f,1024))
   {
      
$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;
      }
   }
   
   
$str decbin($remainder);
   
$str str_pad($str32'0'STR_PAD_LEFT);
   
$remainder bindec(strrev($str));
   return 
$remainder 0xffffffff;
}
?>

<?php
$a 
microtime(); 
echo 
dechex(crc32_file('filename.ext'))."\n"
$b microtime(); 
echo 
array_sum(explode(' ',$b)) - array_sum(explode(' ',$a))."\n";
?>
Output:
ec7369fe
2.384134054184 (or similiar)

carlos at dimension-e dot net (2010-08-26 19:36:02)

This crc32 issue on 64 bits servers may not be a bug, but for sure it wracks many applications when the server migrates to a linux 64 bit machine.
For example, many database fields are set to accept signed 32 bits integers. This odd behavior makes those fields to be filled with the 2147483647 value, which es the higest possible number to be saved in this type of field.
It seems the PHP team regards this as a operative system issue, rather than a language issue, but the result is just the same: You just can not rely on this for data comparison between machines.

jian at theorchard dot com (2010-02-17 10:13:28)

This function returns an unsigned integer from a 64-bit Linux platform.  It does return the signed integer from other 32-bit platforms even a 64-bit Windows one.

The reason is because the two constants PHP_INT_SIZE and PHP_INT_MAX have different values on the 64-bit Linux platform.

I've created a work-around function to handle this situation.

<?php
function get_signed_int($in) {
    
$int_max pow(231)-1;
    if (
$in $int_max){
        
$out $in $int_max 2;
    }
    else {
        
$out $in;
    }
    return 
$out;
}
?>

Hope this helps.

berna (at) gensis (dot) com (dot) br (2009-09-29 20:16:09)

For those who want a more familiar return value for the function:

<?php
function strcrc32($text) {
  
$crc crc32($text);
  if (
$crc 0x80000000) {
    
$crc ^= 0xffffffff;
    
$crc += 1;
    
$crc = -$crc;
  }
  return 
$crc;
}
?>

And to show the result in Hex string:

<?php
function int32_to_hex($value) {
  
$value &= 0xffffffff;
  return 
str_pad(strtoupper(dechex($value)), 8"0"STR_PAD_LEFT);
}
?>

Anonymous (2009-07-16 01:26:49)

<?php
  
echo crc32('example')+4294967296;
?>

gives you the same result as the CRC32() function in MySQL (>=4.1)

"SELECT CRC32('example')"

vice versa

"SELECT CRC32('example')-4294967296"

in MySQL gives you the same result as:

<?php
  
echo  crc32('example');
?>

angelo (at) mandato (period) com (2008-01-18 06:54:25)

From my tests noted below, md5_file() function is the best function for performing file verification. This will remain the case until a native crc32_file() function is added to PHP.

file_crc() function that Bulk at bulksplace dot com posted is the most efficient solution on Windows for small and medium size files.  It is most likely because file_get_contents() uses memory mapping techniques.  Unfortunately on Linux (Fedora), the results were slightly better for md5_file().

sha1_file() on large files is slower than md5_file().  The time it takes for the __crc32_file() function found below is linear to the size of the file.  I would avoid using __crc32_file().  The file_crc() function will fail when using the file_get_contents() if the file is larger than the PHP.ini memory_limit setting.  Windows does not seem to use the memory_limit for file_get_contents(), but I did run into an error 'FATAL: emalloc(): Unable to allocate x bytes' when testing iso files.

I ran the following tests on both WindowsXP and Fedora 4 machines.

<?php
   
// File verification tests by Angelo Mandato (angelo [at] mandato {period} com)
  
   // __crc32_file() is very slow, you can uncomment to test for yourself.
   //require_once('crc32_file.php');
   // Copy and paste the contents of the crc32_file() code found on
   // the php.net crc32 PHP manual page in a new file and save
   // as crc32_file.php in the same directory as this script.
 
   // Get microseconds
   
function GetMicrotime()
   {
       list(
$usec$sec) = explode(" "microtime());
       return ((float)
$usec + (float)$sec);
   }
  
   
// file_crc() - function to test
   
function file_crc($file)
   {
       
$file_string file_get_contents($file);
       
$crc crc32($file_string);
       return 
sprintf("%u"$crc);
   }

   
$Methods = array('sha1_file()''md5_file()''file_crc()');
   if( 
function_exists('__crc32_file') )
       
$Methods[] = '__crc32_file()';
   
$directory '/path/to/directory/'// Don't forget trailing backslash.
   
$files scandir($directory);
  
   for( 
$method_index 0$method_index count($Methods); $method_index++ )
   {
       
$start_time GetMicrotime();
       while( list(
$index,$file) = each($files) )
       {
           if( 
$file != '.' && $file != '..' && is_file($directory.$file) )
           {
               switch( 
$method_index )
               {
                   case 
0: { // sha1_file()
                       
$value sha1_file($directory.$file);
                   }; break;
                   case 
1: { // md5_file()
                       
$value md5_file($directory.$file);
                   }; break;
                   case 
2: { // file_crc()
                       
$value file_crc($directory.$file);
                   }; break;
                   case 
3: { // __crc32_file()
                       
$value __crc32_file($directory.$file);
                   }; break;
               }
           }
           else 
// It is not part of our test results, lets remove it from the array
           
{
               unset(
$files[$index]);
           }
       }
       
$end_time GetMicrotime();
       echo 
sprintf("%s took %.03f seconds to calculate %d files.\n"$Methods[$method_index], $end_time-$start_timecount($files) );
       
reset($files); // Reset pointer in array
   
}
   echo 
"file verification tests completed.\n";
?>

It would be nice if a crc32_file() function was added to PHP natively.

I am not sure why anyone removed this post from this thread, but this is very useful information. and I believe it should remain.  If you're the moderator and deleted this before, please contact me and explain why it was removed. This is not a question, a report of a bug nor a feature request.  This is factual information that is useful to all.

dave at jufer dot info (2007-12-03 14:15:27)

This function returns the same int value on a 64 bit mc. like the crc32() function on a 32 bit mc.

<?php
function crcKw($num){
    
$crc crc32($num);
    if(
$crc 0x80000000){
        
$crc ^= 0xffffffff;
        
$crc += 1;
        
$crc = -$crc;
    }
    return 
$crc;
}
?>

Ren (2007-10-03 11:53:47)

Dealing with 32 bit unsigned values overflowing 32 bit php signed values can be done by adding 0x10000000 to any unexpected negative result, rather than using sprintf.
$i = crc32('1');
printf("%u\n", $i);
if (0 > $i)
{
// Implicitly casts i as float, and corrects this sign.
$i += 0x100000000;
}
var_dump($i);
Outputs:
2212294583
float(2212294583)

petteri at qred dot fi (2007-06-28 23:03:30)

If you have php version<5.1.2 you might use this.
It's a little bit faster than __crc32_file() :)

Ps. crc32_combine() is ported directly from zlib.

<?php
function crc32_file($filename)
{
    
$fp=fopen($filename"rb");
    
$old_crc=false;

    if (
$fp != false) {
        
$buffer '';
        
        while (!
feof($fp)) {
            
$buffer=fread($fp10485760); 
            
$len=strlen($buffer);       
            
$t=crc32($buffer);    
        
            if (
$old_crc) {
                
$crc32=crc32_combine($old_crc$t$len);
                
$old_crc=$crc32;
            } else {
                
$crc32=$old_crc=$t;
            }
        }
        
fclose($fp);
    } else {
        print 
"Cannot open file\n";
    }

    return 
$crc32;
}

function 
crc32_combine($crc1$crc2$len2)
{
    
$odd[0]=0xedb88320;
    
$row=1;

    for(
$n=1;$n<32;$n++) {
        
$odd[$n]=$row;
        
$row<<=1;
    }

    
gf2_matrix_square($even,$odd);
    
gf2_matrix_square($odd,$even);

    do {
        
/* apply zeros operator for this bit of len2 */
        
gf2_matrix_square($even$odd);

        if (
$len2 1)
            
$crc1=gf2_matrix_times($even$crc1);

        
$len2>>=1;
    
        
/* if no more bits set, then done */
        
if ($len2==0)
            break;
    
        
/* another iteration of the loop with odd and even swapped */
        
gf2_matrix_square($odd$even);
        if (
$len2 1)
            
$crc1=gf2_matrix_times($odd$crc1);
        
$len2>>= 1;
    
    } while (
$len2 != 0);

    
$crc1 ^= $crc2;
    return 
$crc1;
}

function 
gf2_matrix_square(&$square, &$mat)
{
    for (
$n=0;$n<32;$n++) {
        
$square[$n]=gf2_matrix_times($mat$mat[$n]);
    }
}

function 
gf2_matrix_times($mat$vec)
{
    
$sum=0;
    
$i=0;
    while (
$vec) {
        if (
$vec 1) {
            
$sum ^= $mat[$i];
        }
        
$vec>>= 1;
        
$i++;
    }
    return 
$sum;
}
?>

slimshady451 (2007-06-20 02:14:58)

I see a lot of function for crc32_file, but for php version >= 5.1.2 don't forget you can use this :

<?php
function crc32_file($filename)
{
    return 
hash_file ('CRC32'$filename FALSE );
}
?>

Using crc32(file_get_contents($filename)) will use too many memory on big file so don't use it.

mail at tristansmis dot nl (2007-05-30 01:36:32)

I used the abs value of this function on a 32-bit system. When porting the code to a 64-bit system I’ve found that the value is different. The following code has the same outcome on both systems.
<?php

   $crc 
abs(crc32($string));
   if( 
$crc 0x80000000){
      
$crc ^= 0xffffffff;
      
$crc += 1;
   }

   
/* Old solution
    * $crc = abs(crc32($string))
    */

?>

roberto at spadim dot com dot br (2006-04-07 21:52:04)

MODBUS RTU, CRC16, 
input-> modbus rtu string
output -> 2bytes string, in correct modbus order

<?php
function crc16($string,$length=0){

    
$auchCRCHi=array(    0x000xC10x810x400x010xC00x800x410x010xC00x800x410x000xC10x81,
                
0x400x010xC00x800x410x000xC10x810x400x000xC10x810x400x010xC0,
                
0x800x410x010xC00x800x410x000xC10x810x400x000xC10x810x400x01,
                
0xC00x800x410x000xC10x810x400x010xC00x800x410x010xC00x800x41,
                
0x000xC10x810x400x010xC00x800x410x000xC10x810x400x000xC10x81,
                
0x400x010xC00x800x410x000xC10x810x400x010xC00x800x410x010xC0,
                
0x800x410x000xC10x810x400x000xC10x810x400x010xC00x800x410x01,
                
0xC00x800x410x000xC10x810x400x010xC00x800x410x000xC10x810x40,
                
0x000xC10x810x400x010xC00x800x410x010xC00x800x410x000xC10x81,
                
0x400x000xC10x810x400x010xC00x800x410x000xC10x810x400x010xC0,
                
0x800x410x010xC00x800x410x000xC10x810x400x000xC10x810x400x01,
                
0xC00x800x410x010xC00x800x410x000xC10x810x400x010xC00x800x41,
                
0x000xC10x810x400x000xC10x810x400x010xC00x800x410x000xC10x81,
                
0x400x010xC00x800x410x010xC00x800x410x000xC10x810x400x010xC0,
                
0x800x410x000xC10x810x400x000xC10x810x400x010xC00x800x410x01,
                
0xC00x800x410x000xC10x810x400x000xC10x810x400x010xC00x800x41,
                
0x000xC10x810x400x010xC00x800x410x010xC00x800x410x000xC10x81,
                
0x40);
    
$auchCRCLo=array(    0x000xC00xC10x010xC30x030x020xC20xC60x060x070xC70x050xC50xC4,
                
0x040xCC0x0C0x0D0xCD0x0F0xCF0xCE0x0E0x0A0xCA0xCB0x0B0xC90x09,
                
0x080xC80xD80x180x190xD90x1B0xDB0xDA0x1A0x1E0xDE0xDF0x1F0xDD,
                
0x1D0x1C0xDC0x140xD40xD50x150xD70x170x160xD60xD20x120x130xD3,
                
0x110xD10xD00x100xF00x300x310xF10x330xF30xF20x320x360xF60xF7,
                
0x370xF50x350x340xF40x3C0xFC0xFD0x3D0xFF0x3F0x3E0xFE0xFA0x3A,
                
0x3B0xFB0x390xF90xF80x380x280xE80xE90x290xEB0x2B0x2A0xEA0xEE,
                
0x2E0x2F0xEF0x2D0xED0xEC0x2C0xE40x240x250xE50x270xE70xE60x26,
                
0x220xE20xE30x230xE10x210x200xE00xA00x600x610xA10x630xA30xA2,
                
0x620x660xA60xA70x670xA50x650x640xA40x6C0xAC0xAD0x6D0xAF0x6F,
                
0x6E0xAE0xAA0x6A0x6B0xAB0x690xA90xA80x680x780xB80xB90x790xBB,
                
0x7B0x7A0xBA0xBE0x7E0x7F0xBF0x7D0xBD0xBC0x7C0xB40x740x750xB5,
                
0x770xB70xB60x760x720xB20xB30x730xB10x710x700xB00x500x900x91,
                
0x510x930x530x520x920x960x560x570x970x550x950x940x540x9C0x5C,
                
0x5D0x9D0x5F0x9F0x9E0x5E0x5A0x9A0x9B0x5B0x990x590x580x980x88,
                
0x480x490x890x4B0x8B0x8A0x4A0x4E0x8E0x8F0x4F0x8D0x4D0x4C0x8C,
                
0x440x840x850x450x870x470x460x860x820x420x430x830x410x810x80,
                
0x40);
    
$length        =($length<=0?strlen($string):$length);
    
$uchCRCHi    =0xFF;
    
$uchCRCLo    =0xFF;
    
$uIndex        =0;
    for (
$i=0;$i<$length;$i++){
        
$uIndex        =$uchCRCLo ord(substr($string,$i,1));
        
$uchCRCLo    =$uchCRCHi $auchCRCHi[$uIndex];
        
$uchCRCHi    =$auchCRCLo[$uIndex] ;
    }
    return(
chr($uchCRCLo).chr($uchCRCHi));
}
?>

Bulk at bulksplace dot com (2005-08-27 05:46:12)

A faster way I've found to return CRC values of larger files, is instead of using the file()/implode() method used below, is to us file_get_contents() (PHP 4 >= 4.3.0) which uses memory mapping techniques if supported by your OS to enhance performance. Here's my example function: 

<?php
// $file is the path to the file you want to check.
function file_crc($file)
{
    
$file_string file_get_contents($file);

    
$crc crc32($file_string);
    
    return 
sprintf("%u"$crc);
}

$file_to_crc = /home/path/to/file.jpg;

echo 
file_crc($file_to_crc); // Outputs CRC value for given file.
?>

I've found in testing this method is MUCH faster for larger binary files.

waldomonster at netjukebox dot demon dot nl (2004-04-23 08:48:52)

<?php
$data 
'dot';
echo 
dechex(crc32($data));
?>

Returns 59278a3
Witch is missing a leading zero.

<?php
$data 
'dot';
echo 
str_pad(dechex(crc32($data)), 8'0'STR_PAD_LEFT);
?>

Returns the correct string: 059278a3

arachnid at notdot dot net (2004-04-13 20:44:12)

Note that the CRC32 algorithm should NOT be used for cryptographic purposes, or in situations where a hostile/untrusted user is involved, as it is far too easy to generate a hash collision for CRC32 (two different binary strings that have the same CRC32 hash). Instead consider SHA-1 or MD5.

same (2004-02-01 17:27:27)

bit by bit crc32 computation

<?php

function bitbybit_crc32($str,$first_call=false){

    
//reflection in 32 bits of crc32 polynomial 0x04C11DB7
    
$poly_reflected=0xEDB88320;

    
//=0xFFFFFFFF; //keep track of register value after each call
    
static $reg=0xFFFFFFFF;

    
//initialize register on first call
    
if($first_call$reg=0xFFFFFFFF;
    
    
$n=strlen($str);
    
$zeros=$n<$n 4;

    
//xor first $zeros=min(4,strlen($str)) bytes into the register
    
for($i=0;$i<$zeros;$i++)
        
$reg^=ord($str{$i})<<$i*8;

    
//now for the rest of the string
    
for($i=4;$i<$n;$i++){
        
$next_char=ord($str{$i});
        for(
$j=0;$j<8;$j++)
            
$reg=(($reg>>1&0x7FFFFFFF)|($next_char>>$j&1)<<0x1F)
                ^(
$reg&1)*$poly_reflected;
    }

    
//put in enough zeros at the end
    
for($i=0;$i<$zeros*8;$i++)
        
$reg=($reg>>1&0x7FFFFFFF)^($reg&1)*$poly_reflected;

    
//xor the register with 0xFFFFFFFF
    
return ~$reg;
}

$str="123456789"//whatever
$blocksize=4//whatever

for($i=0;$i<strlen($str);$i+=$blocksize$crc=bitbybit_crc32(substr($str,$i,$blocksize),!$i);

?>

xethmir at yournextclient dot com (2003-07-16 19:12:48)

This is a really simple way of displaying the crc-32 hexadecimal code/checksum for a file... (absolute paths are more reliable)

<?php
$file 
"http://example.com/bar.jpg";

// Read the file into an array
$data file($file);

// Join the array into a string
$data implode(''$data);

// Calculate the crc
$crc crc32($data);

//convert from decimal to hexadecimal
$crchex=DecHex($crc*1);

//echo the result
echo "$crchex";
?>

quix at free dot fr (2003-05-05 13:19:18)

I needed the crc32 of a file that was pretty large, so I didn't want to read it into memory.
So I made this:

<?php
    $GLOBALS
['__crc32_table']=array();        // Lookup table array
    
__crc32_init_table();

    function 
__crc32_init_table() {            // Builds lookup table array
        // This is the official polynomial used by
        // CRC-32 in PKZip, WinZip and Ethernet.
        
$polynomial 0x04c11db7;

        
// 256 values representing ASCII character codes.
        
for($i=0;$i <= 0xFF;++$i) {
            
$GLOBALS['__crc32_table'][$i]=(__crc32_reflect($i,8) << 24);
            for(
$j=0;$j 8;++$j) {
                
$GLOBALS['__crc32_table'][$i]=(($GLOBALS['__crc32_table'][$i] << 1) ^
                    ((
$GLOBALS['__crc32_table'][$i] & (<< 31))?$polynomial:0));
            }
            
$GLOBALS['__crc32_table'][$i] = __crc32_reflect($GLOBALS['__crc32_table'][$i], 32);
        }
    }

    function 
__crc32_reflect($ref$ch) {        // Reflects CRC bits in the lookup table
        
$value=0;
        
        
// Swap bit 0 for bit 7, bit 1 for bit 6, etc.
        
for($i=1;$i<($ch+1);++$i) {
            if(
$ref 1$value |= (<< ($ch-$i));
            
$ref = (($ref >> 1) & 0x7fffffff);
        }
        return 
$value;
    }

    function 
__crc32_string($text) {        // Creates a CRC from a text string
        // Once the lookup table has been filled in by the two functions above,
        // this function creates all CRCs using only the lookup table.

        // You need unsigned variables because negative values
        // introduce high bits where zero bits are required.
        // PHP doesn't have unsigned integers:
        // I've solved this problem by doing a '&' after a '>>'.

        // Start out with all bits set high.
        
$crc=0xffffffff;
        
$len=strlen($text);

        
// Perform the algorithm on each character in the string,
        // using the lookup table values.
        
for($i=0;$i $len;++$i) {
            
$crc=(($crc >> 8) & 0x00ffffff) ^ $GLOBALS['__crc32_table'][($crc 0xFF) ^ ord($text{$i})];
        }
        
        
// Exclusive OR the result with the beginning value.
        
return $crc 0xffffffff;
    }
    
    function 
__crc32_file($name) {            // Creates a CRC from a file
        // Info: look at __crc32_string

        // Start out with all bits set high.
        
$crc=0xffffffff;

        if((
$fp=fopen($name,'rb'))===false) return false;

        
// Perform the algorithm on each character in file
        
for(;;) {
            
$i=@fread($fp,1);
            if(
strlen($i)==0) break;
            
$crc=(($crc >> 8) & 0x00ffffff) ^ $GLOBALS['__crc32_table'][($crc 0xFF) ^ ord($i)];
        }
        
        @
fclose($fp);
        
        
// Exclusive OR the result with the beginning value.
        
return $crc 0xffffffff;
    }
?>

spectrumizer at cycos dot net (2002-12-29 15:30:51)

Here is a tested and working CRC16-Algorithm:

<?php
function crc16($string) {
  
$crc 0xFFFF;
  for (
$x 0$x strlen ($string); $x++) {
    
$crc $crc ord($string[$x]);
    for (
$y 0$y 8$y++) {
      if ((
$crc 0x0001) == 0x0001) {
        
$crc = (($crc >> 1) ^ 0xA001);
      } else { 
$crc $crc >> 1; }
    }
  }
  return 
$crc;
}
?>

Regards,
Mario

易百教程