在PHP 中, pack()和unpack()是一對功能強大的函數,它們常被用於在二進制數據和人類可讀格式之間轉換。本文將帶你了解如何利用這兩個函數創建一個簡單的雙向數據轉換器,實現數據結構的序列化與反序列化操作,適用於文件保存、網絡傳輸等多種場景。
pack() :根據指定的格式,把一個或多個值打包成二進製字符串。
unpack() :按照指定的格式,從二進製字符串中解析出值。
這兩個函數的格式代碼支持多種數據類型,比如整型、浮點型、字符串等。常見的格式字符有:
格式字符 | 含義 | 佔用字節 |
---|---|---|
C | 無符號char | 1 字節 |
n | 無符號短整型(big endian) | 2 字節 |
N | 無符號長整型(big endian) | 4 字節 |
a | NUL 填充字符串 | N 字節 |
假設我們需要對以下結構的數據進行打包和解包操作:
用戶ID(4字節無符號整數)
用戶等級(1字節)
是否激活(布爾值,用0 和1 表示)
用戶名(固定長度字符串,20字節)
我們要實現的目標是:
利用pack()把這些字段打包成一個二進製字符串。
利用unpack()從這個字符串中重新解析出原始數據。
class DataConverter {
const FORMAT = 'Nid/Clevel/Cactive/a20username';
public static function encode($data) {
return pack(
self::FORMAT,
$data['id'],
$data['level'],
$data['active'] ? 1 : 0,
$data['username']
);
}
public static function decode($binary) {
$result = unpack(self::FORMAT, $binary);
$result['active'] = $result['active'] === 1;
$result['username'] = rtrim($result['username'], "\0"); // 去除 NUL 填充
return $result;
}
}
$data = [
'id' => 123456,
'level' => 5,
'active' => true,
'username' => 'm66user'
];
$binary = DataConverter::encode($data);
echo bin2hex($binary) . PHP_EOL;
$parsed = DataConverter::decode($binary);
print_r($parsed);
輸出示例(十六進製表示):
0001e24005016d363675736572000000000000000000000000
Array
(
[id] => 123456
[level] => 5
[active] => 1
[username] => m66user
)
這個轉換器雖然簡單,但它可以延伸到更複雜的使用場景:
網絡協議封包,例如構造與解析socket 通信數據。
二進製文件的序列化與反序列化。
在需要數據緊湊存儲(如緩存、嵌入設備)的情況下使用。
比如,你可以將編碼後的數據發送到遠程接口:
file_put_contents("https://m66.net/api/upload", $binary);
或者從遠程加載數據解碼: