當前位置: 首頁> 最新文章列表> 結合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. 定義自定義數據結構示例

假設我們定義一種簡單的數據結構如下:

字段名類型長度(字節)說明
type uint8 1數據類型標識
length uint16 2後續數據長度
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也能輕鬆應對網絡協議、文件格式解析等場景。