在PHP 中, pack()函數用於將數據按照指定格式打包成二進製字符串。很多開發者在處理網絡協議或二進製文件時,會用到它。 pack("N", 12345)是一個典型的用法,代表將整數12345按照大端字節序(網絡字節序)打包成4字節的二進製字符串。
但有時你可能會發現,使用pack("N", 12345)後得到的結果和你預期的輸出不一致,甚至在轉成十六進製或輸出時看起來“奇怪”。這到底是為什麼呢?本文幫你分析背後的原理。
格式符"N"在pack()中表示:
N :unsigned long(4字節,32位無符號整數)
大端字節序(big-endian),即高字節在前,低字節在後
舉例來說,整數12345的十六進製表示是0x3039 ,其對應的4字節大端序是:
00 00 30 39
所以pack("N", 12345)生成的二進制串,轉成十六進制應該是這4個字節。
很多人觀察到結果“看起來不對”,常見原因包括:
直接輸出二進製字符串到瀏覽器或終端,其中包含很多不可見字符,或者某些字節被解析成控製字符,看起來像亂碼。
沒有將二進制結果轉換成可讀格式,例如十六進製或base64。
對結果的期望和實際含義不匹配,例如以為pack("N", 12345)會直接輸出數字字符串“12345”。
假設我們寫下面的PHP 代碼:
<?php
$binary = pack("N", 12345);
echo bin2hex($binary);
?>
運行結果是:
00003039
這就是期望中的4字節大端序結果。
如果直接用echo $binary; ,你會看到亂碼或空白,因為$binary是二進制數據,不是普通文本。
錯誤示範:
<?php
echo pack("N", 12345);
?>
輸出到網頁或終端時,你會看到亂碼或沒有任何可見字符。這讓你誤以為pack()結果不對。
pack("N", 12345)按大端字節序返回4字節二進製字符串,代表數字12345。
結果是二進制數據,不是字符串“12345”。
查看結果時,最好用bin2hex()或類似方法轉換成可讀格式。
直接輸出二進制可能導致看似“奇怪”的結果,但並非錯誤。
<?php
// 將數字12345打包成4字節大端二進制
$binary = pack("N", 12345);
// 顯示二進制的十六進製表示,方便觀察
echo "Hex representation: " . bin2hex($binary) . "\n";
// 也可以使用 unpack 反解驗證
$unpacked = unpack("N", $binary);
echo "Unpacked number: " . $unpacked[1] . "\n";
?>
執行後輸出:
Hex representation: 00003039
Unpacked number: 12345
PHP 官方文檔關於pack
了解字節序(Endian)對二進制數據處理的重要性
網絡協議與二進制數據的關係