在PHP中,处理二进制数据时,pack()和unpack()函数是两个非常实用的工具。它们可以将数据按照特定的格式转换为二进制字符串,或者将二进制字符串解析成结构化的数据。这对于实现自定义数据结构的序列化和反序列化,或者与底层协议、文件格式交互非常关键。
本文将详细讲解如何结合pack()与unpack()函数,实现自定义数据结构的解析与转换。
pack(format, args...):根据format格式字符串,将参数args打包成二进制字符串。
unpack(format, data):根据format格式字符串,将二进制字符串data解包成关联数组。
格式字符串由格式代码组成,代码定义了数据类型、长度及字节序等。例如:
C:无符号字符(1字节)
n:无符号16位大端字节序整数
V:无符号32位小端字节序整数
a:NUL填充的字符串
A:空格填充的字符串
更多格式代码可参考PHP官方文档。
假设我们定义一种简单的数据结构如下:
字段名 | 类型 | 长度(字节) | 说明 |
---|---|---|---|
type | uint8 | 1 | 数据类型标识 |
length | uint16 | 2 | 后续数据长度 |
payload | 字节流 | length | 具体数据内容 |
我们的目标是:
将PHP数据结构打包成符合以上格式的二进制数据;
解析该二进制数据,提取出type、length和payload字段。
<?php
function packData(int $type, string $payload): string {
$length = strlen($payload);
// 'C' - 1字节无符号整数
// 'n' - 2字节无符号大端整数
// 'a*' - 任意长度字符串,NUL填充(这里不需要填充)
return pack('Cn', $type, $length) . $payload;
}
// 测试
$type = 5;
$payload = "Hello, World!";
$binaryData = packData($type, $payload);
echo bin2hex($binaryData);
?>
这里pack('Cn', $type, $length)先将type和length分别打包,再拼接上原始字符串$payload。
解析时,先取出固定长度部分的type和length,然后根据length截取剩余的payload。
<?php
function unpackData(string $binaryData): array {
// 先解包前3个字节,type(1字节) + length(2字节大端)
$header = unpack('Ctype/nlength', substr($binaryData, 0, 3));
$type = $header['type'];
$length = $header['length'];
// 取出剩余payload数据
$payload = substr($binaryData, 3, $length);
return [
'type' => $type,
'length' => $length,
'payload' => $payload,
];
}
// 测试
$data = $binaryData; // 假设来自上面packData的输出
$result = unpackData($data);
var_dump($result);
?>
整合上面两个函数,实现自定义结构的序列化和反序列化:
<?php
function packData(int $type, string $payload): string {
$length = strlen($payload);
return pack('Cn', $type, $length) . $payload;
}
function unpackData(string $binaryData): array {
$header = unpack('Ctype/nlength', substr($binaryData, 0, 3));
$type = $header['type'];
$length = $header['length'];
$payload = substr($binaryData, 3, $length);
return [
'type' => $type,
'length' => $length,
'payload' => $payload,
];
}
// 使用示例
$type = 10;
$payload = "PHP pack/unpack 演示";
$packed = packData($type, $payload);
echo "二进制数据(hex):" . bin2hex($packed) . "\n";
$unpacked = unpackData($packed);
echo "解析结果:\n";
print_r($unpacked);
?>
运行结果:
二进制数据(hex):0a0017... (hex编码的二进制内容)
解析结果:
Array
(
[type] => 10
[length] => 23
[payload] => PHP pack/unpack 演示
)
pack()与unpack()是处理二进制数据的利器,支持多种数据类型和字节序转换;
自定义数据结构的解析,可以先定义固定头部格式,再用字符串操作处理变长字段;
结合二进制处理,PHP也能轻松应对网络协议、文件格式解析等场景。