在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也能輕鬆應對網絡協議、文件格式解析等場景。