本文目录导读:

在 PHP 中,pack() 和 unpack() 函数用于在二进制数据和 PHP 变量之间进行转换,以下是详细的使用说明:
pack() 函数 - 将数据打包成二进制字符串
基本语法
pack(string $format, mixed ...$values): string
常用格式字符
| 格式 | 说明 | 示例 |
|---|---|---|
a |
NUL 填充字符串 | a10 - 10字节字符串 |
A |
空格填充字符串 | A10 - 10字节字符串 |
c |
有符号字符(1字节) | c |
C |
无符号字符(1字节) | C |
s |
有符号短整数(2字节) | s |
S |
无符号短整数(2字节) | S |
n |
无符号短整数(大端序) | n |
v |
无符号短整数(小端序) | v |
i |
有符号整数(机器相关) | i |
I |
无符号整数(机器相关) | I |
l |
有符号长整数(4字节) | l |
L |
无符号长整数(4字节) | L |
N |
无符号长整数(大端序,4字节) | N |
V |
无符号长整数(小端序,4字节) | V |
f |
单精度浮点数 | f |
d |
双精度浮点数 | d |
使用示例
// 1. 基本整数打包
$packed = pack('C', 65); // 输出: "A" (ASCII 65)
echo bin2hex($packed); // 输出: 41
// 2. 多个值打包
$packed = pack('C4', 65, 66, 67, 68); // 打包4个字符
echo $packed; // 输出: "ABCD"
// 3. 混合类型
$packed = pack('nvc', 0x1234, 0x5678, 0x9A);
// n: 无符号短整数(大端序)
// v: 无符号短整数(小端序)
// c: 有符号字符
echo bin2hex($packed); // 输出: "123478569a"
// 4. 字符串打包
$packed = pack('a10', 'Hello');
echo strlen($packed); // 输出: 10 (用null填充)
$packed = pack('A10', 'Hello');
echo strlen($packed); // 输出: 10 (用空格填充)
// 5. 使用数字重复格式
$packed = pack('C*', 1, 2, 3, 4); // 打包所有参数
unpack() 函数 - 解包二进制字符串
基本语法
unpack(string $format, string $string): array
使用示例
// 1. 解包单个值
$packed = pack('C', 65);
$result = unpack('Cchar', $packed);
echo $result['char']; // 输出: 65
// 2. 解包多个值
$packed = pack('C4', 65, 66, 67, 68);
$result = unpack('Ca/Cb/Cc/Cd', $packed);
print_r($result);
// 输出: ['a' => 65, 'b' => 66, 'c' => 67, 'd' => 68]
// 3. 解包整数
$packed = pack('n', 0x1234);
$result = unpack('nint', $packed);
echo $result['int']; // 输出: 4660 (0x1234)
// 4. 解包浮点数
$packed = pack('f', 3.14);
$result = unpack('ffloat', $packed);
echo $result['float']; // 输出: 3.14
// 5. 解包字符串
$packed = pack('a10', 'Hello');
$result = unpack('a10str', $packed);
echo rtrim($result['str']); // 输出: "Hello"
// 6. 重复解包
$packed = pack('C*', 1, 2, 3, 4, 5);
$result = unpack('C5nums', $packed);
print_r($result);
// 输出: ['nums1' => 1, 'nums2' => 2, 'nums3' => 3, 'nums4' => 4, 'nums5' => 5]
// 7. 使用 * 解包所有
$result = unpack('C*', $packed);
print_r($result);
// 输出: [1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5]
实用示例
创建二进制文件格式
// 创建一个简单的二进制文件
function writeBinaryFile($filename, $data) {
// 写入文件头:魔数(2字节) + 版本号(2字节) + 文件大小(4字节)
$header = pack('nnV', 0x4D41, 1, strlen($data));
// 写入数据
file_put_contents($filename, $header . $data);
}
// 读取二进制文件
function readBinaryFile($filename) {
$content = file_get_contents($filename);
// 解析文件头
$header = unpack('nmagic/nversion/Vsize', substr($content, 0, 8));
// 读取数据
$data = substr($content, 8, $header['size']);
return [
'magic' => $header['magic'],
'version' => $header['version'],
'size' => $header['size'],
'data' => $data
];
}
网络协议通信
// 创建网络消息
function createMessage($type, $content) {
$payload = pack('n', $type) . $content;
$length = strlen($payload);
return pack('N', $length) . $payload;
}
// 解析网络消息
function parseMessage($buffer) {
if (strlen($buffer) < 4) {
return null;
}
$length = unpack('Nlen', substr($buffer, 0, 4))['len'];
if (strlen($buffer) < 4 + $length) {
return null;
}
$type = unpack('ntype', substr($buffer, 4, 2))['type'];
$content = substr($buffer, 6, $length - 2);
return [
'type' => $type,
'content' => $content
];
}
注意事项
- 字节序问题:注意区分大端序(network byte order)和小端序(little-endian)
- 数据对齐:某些系统可能有字节对齐要求
- 类型范围:确保数据在类型允许的范围内
- 字符串处理:
a和A格式的区别在于填充字符
常用格式组合
// 常见二进制协议格式
$data = pack(
'nCVCV', // 格式:小端序短整数 + 字符 + 无符号整数 + 字符 + 无符号整数
0x1234, // 魔数
1, // 版本
100, // 数据1
2, // 状态
200 // 数据2
);
// 解包上述数据
$result = unpack('nmagic/Cversion/Vdata1/Cstatus/Vdata2', $data);
pack/unpack 在处理二进制数据时非常强大,适用于文件格式解析、网络协议实现、加密算法等领域。