微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PHP Pack / unpack – 它可以处理可变长度的字符串

我一直试图弄清楚Pack / Unpack的PHP实现是否可以做Perl版本能够做的事情.我希望能用PHP做的例子是:

http://perldoc.perl.org/perlpacktut.html#String-Lengths

# pack a message: ASCIIZ, ASCIIZ, length/string, byte
my $msg = pack( 'Z* Z* C/A* C', $src, $dst, $sm, $prio );
# unpack
( $src, $dst, $sm, $prio ) = unpack( 'Z* Z* C/A* C', $msg );

这个Perl代码的作用描述如下:

Combining two pack codes with a slash (/) associates them with a
single value from the argument list. In pack, the length of the
argument is taken and packed according to the first code while the
argument itself is added after being converted with the template code
after the slash.

即你可以打包可变长度的字符串然后一步解压缩它们,而不是先弄清字符串的长度然后再将它作为一个单独的步骤解压缩.

PHP手册没有提到这个功能,任何尝试在解包中插入像’C / A *’这样的模式都给我带来了错误.这是手册中的疏忽还是PHP版本不支持的东西?

解决方法:

遗憾的是,PHP包和解包函数不提供像Perl这样的变量(空终止)字符串的自动打包和解包.

要适应此功能,请考虑将解包函数包装到这样的辅助类中:

class Packer {
    static function unpack($mask, $data, &$pos) {
        try {
            $result = array();
            $pos = 0;
            foreach($mask as $field) {
                $subject = substr($data, $pos);
                $type = $field[0];
                $name = $field[1];
                switch($type) {
                    case 'N':
                    case 'n':
                    case 'C':
                    case 'c':
                        $temp = unpack("{$type}temp", $subject);
                        $result[$name] = $temp['temp'];
                        if($type=='N') {
                            $result[$name] = (int)$result[$name];
                        }

                        $pos += ($type=='N' ? 4 : ($type=='n' ? 2 : 1));
                        break;
                    case 'a':
                        $nullPos = strpos($subject, "\0") + 1;
                        $temp = unpack("a{$nullPos}temp", $subject);
                        $result[$name] = $temp['temp'];
                        $pos += $nullPos;
                        break;
                }
            }
            return $result;
        } catch(Exception $e) {
            $message = $e->getMessage();
            throw new Exception("unpack Failed with error '{$message}'");
        }
    }
}

请注意,此函数不实现所有解压缩类型,仅作为示例.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐