2012-07-24 46 views
3

我一直在试图弄清楚,Pack/Unpack的PHP实现是否可以完成Perl版本能够完成的工作。我希望能在PHP做的例子是: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代码也被描述为:

组合两个包代码以斜线( /)将它们与参数列表中的单个值 相关联。在包装中, 参数的长度根据第一个代码进行取出和打包,而 参数本身在斜杠后与模板代码 一起转换后添加。

即可以包的可变长度字符串,然后解压它们在一个步骤,而不必首先弄清楚字符串的长度,然后提取它作为一个单独的步骤。

PHP手册未提及此功能,并且任何尝试在解包中插入“C/A *”等模式都会给我带来错误。这是手册中的疏忽还是PHP版本不支持的内容?

回答

5

不幸的是,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}'"); 
     } 
    } 
} 

请注意,这个功能没有实现所有的内容解压类型和仅仅作为一个例子。

相关问题