首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何计算压缩包的Adler32校验和?

如何计算压缩包的Adler32校验和?
EN

Stack Overflow用户
提问于 2009-08-22 19:52:17
回答 3查看 4.9K关注 0票数 2

我在服务器端使用Paul Duncans php ZipStream (http://pablotron.org/software/zipstream-php/)的组合,用于动态创建zips,在Flex/Air客户端使用Fzip (http://codeazur.com.br/lab/fzip/)。

在Air中工作得很好,但当在浏览器中运行Flex时,为了读取FZip,压缩包需要在报头中包含Adler32校验和。

我如何计算一个Adler32校验和的压缩在php?

ZipStream核心函数,使用gzdeflate进行压缩,可以在下面看到。

问候/ Jonas

代码语言:javascript
复制
function add_file($name, $data, $opt = array(), $deflateLevel=0) {
    # compress data

    $zdata = gzdeflate($data, $deflateLevel);

    # calculate header attributes

    $crc  = crc32($data);
    $zlen = strlen($zdata);
    $len  = strlen($data);
    $meth = 0x08;

    # send file header
    $this->add_file_header($name, $opt, $meth, $crc, $zlen, $len);

    # print data
    $this->send($zdata);
}

private function add_file_header($name, $opt, $meth, $crc, $zlen, $len) {
    # strip leading slashes from file name
    # (fixes bug in windows archive viewer)
    $name = preg_replace('/^\\/+/', '', $name);

    # calculate name length
    $nlen = strlen($name);

    # create dos timestamp
    $opt['time'] = $opt['time'] ? $opt['time'] : time();
    $dts = $this->dostime($opt['time']);

    # build file header
    $fields = array(            # (from V.A of APPNOTE.TXT)
    array('V', 0x04034b50),     # local file header signature
    array('v', (6 << 8) + 3),   # version needed to extract
    array('v', 0x00),           # general purpose bit flag
    array('v', $meth),          # compresion method (deflate or store)
    array('V', $dts),           # dos timestamp
    array('V', $crc),           # crc32 of data
    array('V', $zlen),          # compressed data length
    array('V', $len),           # uncompressed data length
    array('v', $nlen),          # filename length
    array('v', 0),              # extra data len
    );

    # pack fields and calculate "total" length
    $ret = $this->pack_fields($fields);
    $cdr_len = strlen($ret) + $nlen + $zlen;

    # print header and filename
    $this->send($ret . $name);

    # add to central directory record and increment offset
    $this->add_to_cdr($name, $opt, $meth, $crc, $zlen, $len, $cdr_len);
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-08-22 19:59:51

example implementation in the Wikipedia article翻译过来的

代码语言:javascript
复制
define('MOD_ADLER', 65521);

function adler32($data) {
    $a = 1; $b = 0; $len = strlen($data);
    for ($index = 0; $index < $len; ++$index) {
        $a = ($a + $data[$index]) % MOD_ADLER;
        $b = ($b + $a) % MOD_ADLER;
    }
    return ($b << 16) | $a;
}

并将该整数值转换为字节:

代码语言:javascript
复制
pack('H*', $checksum);
票数 2
EN

Stack Overflow用户

发布于 2010-06-17 17:44:55

对于PHP5CRC5.1.2,您可以使用hash函数,该函数返回>=的十六进制字符串表示:

代码语言:javascript
复制
$dataStr = "abc";
$crcStr = hash('adler32', $dataStr);

更新:有一个bug in hash until mid 2009的字节顺序是错误的。该错误似乎已在5.2.11和5.3.0及更高版本中修复。但对于早期版本,结果的字节顺序需要交换。

更新2:下面是一个包装器函数(和一个测试),可以用来解决这个bug:

代码语言:javascript
复制
<?php

error_reporting(E_ALL);

function hash_adler32_wrapper($data) {
    $digHexStr = hash("adler32", $data);

    // If version is better than 5.2.11 no further action necessary
    if (version_compare(PHP_VERSION, '5.2.11', '>=')) {
        return $digHexStr;
    }

    // Workaround #48284 by swapping byte order
    $boFixed = array();
    $boFixed[0] = $digHexStr[6];
    $boFixed[1] = $digHexStr[7];
    $boFixed[2] = $digHexStr[4];
    $boFixed[3] = $digHexStr[5];
    $boFixed[4] = $digHexStr[2];
    $boFixed[5] = $digHexStr[3];
    $boFixed[6] = $digHexStr[0];
    $boFixed[7] = $digHexStr[1];

    return implode("", $boFixed);
}

// Test fixture, plus expected output generated using the adler32 from zlib
$data_in = "abc";
$expected_out = 0x024d0127;

// PHP's hash function returns a hex hash value as a string so hexdec used to
// convert to number
$hash_out = hexdec(hash("adler32", $data_in));

// Get value via the wrapper function
$wrapper_out = hexdec(hash_adler32_wrapper($data_in));

printf("data_in:          %s\n", $data_in);
printf("expected_out:     0x%08x\n", $expected_out);
printf("builtin hash out: 0x%08x, %s\n", $hash_out,
        ($hash_out == $expected_out)? "OK" : "NOT OK");
printf("wrapper func out: 0x%08x, %s\n", $wrapper_out,
        ($wrapper_out == $expected_out)? "OK" : "NOT OK");

?>
票数 2
EN

Stack Overflow用户

发布于 2010-06-21 04:55:51

Gumbo的解决方案几乎是完美的-但如果参数是字符串而不是字节数组,则需要使用ord()来获取要处理的字符的ascii代码。如下所示:

代码语言:javascript
复制
function adler32($data) {
    $a = 1; $b = 0; $len = strlen($data);
    for ($index = 0; $index < $len; ++$index) {
        $a = ($a + ord($data[$index])) % 65521;
        $b = ($b + $a) % 65521;
    }
    return ($b << 16) | $a;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1316881

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档