当前位置: 首页> 最新文章列表> 结合 unpack() 与 pack() 实现自定义数据结构解析

结合 unpack() 与 pack() 实现自定义数据结构解析

M66 2025-05-27

在PHP中,处理二进制数据时,pack()unpack()函数是两个非常实用的工具。它们可以将数据按照特定的格式转换为二进制字符串,或者将二进制字符串解析成结构化的数据。这对于实现自定义数据结构的序列化和反序列化,或者与底层协议、文件格式交互非常关键。

本文将详细讲解如何结合pack()unpack()函数,实现自定义数据结构的解析与转换。


1. pack()与unpack()函数基础介绍

  • pack(format, args...):根据format格式字符串,将参数args打包成二进制字符串。

  • unpack(format, data):根据format格式字符串,将二进制字符串data解包成关联数组。

格式字符串由格式代码组成,代码定义了数据类型、长度及字节序等。例如:

  • C:无符号字符(1字节)

  • n:无符号16位大端字节序整数

  • V:无符号32位小端字节序整数

  • a:NUL填充的字符串

  • A:空格填充的字符串

更多格式代码可参考PHP官方文档


2. 定义自定义数据结构示例

假设我们定义一种简单的数据结构如下:

字段名类型长度(字节)说明
typeuint81数据类型标识
lengthuint162后续数据长度
payload字节流length具体数据内容

我们的目标是:

  • 将PHP数据结构打包成符合以上格式的二进制数据;

  • 解析该二进制数据,提取出type、length和payload字段。


3. 使用pack()打包数据

<?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)先将typelength分别打包,再拼接上原始字符串$payload


4. 使用unpack()解析数据

解析时,先取出固定长度部分的typelength,然后根据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);
?>

5. 完整示例及说明

整合上面两个函数,实现自定义结构的序列化和反序列化:

<?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 演示
)

6. 总结

  • pack()unpack()是处理二进制数据的利器,支持多种数据类型和字节序转换;

  • 自定义数据结构的解析,可以先定义固定头部格式,再用字符串操作处理变长字段;

  • 结合二进制处理,PHP也能轻松应对网络协议、文件格式解析等场景。