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}'");
        }
    }
}

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

上一篇:ArrayList LinkedList Vector


下一篇:javaNIO学习