前言:直接参照官网。
PHP: pack - Manual PHP中文手册 PHP中国镜像 php 国内镜像 PHP官方网站
PHP: unpack - Manual PHP中文手册 PHP中国镜像 php 国内镜像 PHP官方网站
1、作用
(1)pack:将数据打包成二进制字符串。将输入数据打包成format格式的二进制字符串。
pack(string
$format
, mixed...$values
): string
(2)unpack:根据指定的format将二进制字符串解包成数组。
注:对于一个二进制字符串可能是由多部分组成,每部分都是一个<K,V>,多个就是k-v数组了。待会儿看个具体的例子就知道了。
unpack(string
$format
, string$string
, int$offset
= 0): array|false
支持的格式如下:
我们简单的关注下几种格式即可。
#n 无符号短整型(16位,大端字节序) 高尾端 尾端放在高地址 #v 无符号短整型(16位,小端字节序) 低尾端 尾端放在低地址 #c 有符号字符 #C 无符号字符
2、使用方式
(1)pack的使用。
#同时将4部分数据按照分别指定的格式打包为二进制字符串,格式如下。
#①将16进制数据0x1234按照n(无符号短整型(16位,大端字节序))格式打包成二进制字符串
#②将16进制数据0x5678按照v(无符号短整型(16位,小端字节序))格式打包成二进制字符串
#③将10进制数据65按照c(有符号字符)格式打包成二进制字符串
#④将10进制数据66按照c(无符号字符)格式打包成二进制字符串
<?php
$binarydata = pack("nvcC", 0x1234, 0x5678, 65, 66);
print_r("packresult:" . $binarydata); #4xVAB
print_r("<pre>");
?>
输出如下。注:后面会针对这四个元素挨个分析,明确这个“4xVAB”是怎么来的。
(2)unpack的使用。
$elems = unpack("nelem1/velem2/celem3/Celem4", $binarydata);
①知道这个二进制字符串由四部分组成,每部分的格式分别为nvcC;
②上述加了红色背景的就是指定格式,这个要和打包的时候指定的格式保持一致;
③后面紫色的elem1/elem2/elem3/elem4就是你自己取的名字,方便后续对没部分的引用。
④对照输出结果,一目了然。
#对于上面构建的二进制字符串进行unpack。
#已知其由nccC四部分组成就用着四部分就行解析即可。
<?php
$binarydata = pack("nvcC", 0x1234, 0x5678, 65, 66);
print_r("packresult:" . $binarydata); #4xVAB
print_r("<pre>");
$elems = unpack("nelem1/velem2/celem3/Celem4", $binarydata);
print_r($elems);
print_r("<pre>");
?>
packresult:4xVAB
Array
(
[elem1] => 4660
[elem2] => 22136
[elem3] => 65
[elem4] => 66
)
输出结果如下:
显然,4660就是0x1234的十进制结果、22136就是0x5678的十进制结果,65/66同理。
3、具体测试
分析上面这个case,看看直接打印二进制字符串的结果“4xVAB”是怎么来的。
务必对照ascii码表。百度安全验证
#输出了一个4,分析下这个4是怎么来的。
$binarydata = pack("n", 0x1234);
print_r($binarydata);
print_r("<pre>");
#0x12 Bin(00010010) Dec(18) #查询ascii码表0~31分配给了控制字符;这里的18表示"设备控制2"并不对应可见字符。
#0x34 Bin(00110100) Dec(52) #查询ascii码表对应可打印字符"4"
结论:显然4就是这么来的。
$binarydata = pack("v", 0x5678);
print_r($binarydata); #xV
print_r("<pre>");
#0x56 Bin(01010110) Dec(56) #查询ascii码表对应字符V
#0x78 Bin(01111000) Dec(120) #查询ascii码表对应字符x
结论:又因为v表示小端字节序(低尾端,即尾端在低地址);所以先打印的顺序是xV。
$binarydata = pack("c", 65);
print_r($binarydata);
print_r("<pre>");
#Dec(65) #查询ascii码表对应可见字符A
#结论:所以输出了A
$binarydata = pack("c", 66);
print_r($binarydata);
print_r("<pre>");
#Dec(66) #查询ascii码表对应可见字符B
#结论:所以输出了B
注:也就是说直接利用print之类的方法直接打印二进制字符串可能并没有什么实际意义。实际能打印出来的只是这些二进制对应的ascii码而已。
其实和python的pack/unpack本质上差不多。python使用struct处理二进制数据(使用pack和unpack进行打包和解包)_calcsize函数_焱齿的博客-CSDN博客