pack()函數將指定的格式字符串和數據打包成二進製字符串。例如, pack("C", 65)會返回一個包含ASCII 碼為65(即字符"A")的單個字符的二進製字符串。格式字符串用於描述數據的佈局,常用的格式代碼包括:
C :無符號字符(8位,範圍0–255)
n :無符號短整型(16位,大端字節序)
N :無符號長整型(32位,大端字節序)
H* :十六進製字符串(高位優先)
舉個例子:
$bin = pack("C*", 72, 101, 108, 108, 111); // 對應字符 "Hello"
echo $bin; // 輸出 Hello
這個過程就像是將一個整數數組轉換為一個壓縮後的二進製字符串。
與pack()相反, ord()用於將字符轉換成其對應的ASCII 或Unicode 值。它是pack()的“解碼器”,在從二進製字符串中提取數據時非常有用。
例如:
$char = "A";
$ascii = ord($char); // 返回 65
這個函數非常適合與pack()配合,從編碼後的字符串中逐字節恢復原始數據。
將數據編碼為二進制時用pack() ,將其從二進制中提取出來時用ord() 。這構成了兩者互補的關係。比如,我們可以先將一個數字序列打包,然後再逐字節解析出來:
$data = [77, 54, 54];
$bin = pack("C*", ...$data);
// 讀取每個字節
for ($i = 0; $i < strlen($bin); $i++) {
echo ord($bin[$i]) . "\n"; // 輸出 77, 54, 54
}
這段代碼中,我們用pack()將數組[77, 54, 54]轉為一個三字節的二進製字符串,而ord()則逐字節還原為原始數值。
這種技巧在構造特定協議的二進制報文時尤其有用。例如構造一個類似短鏈接請求包:
$url_id = 1234;
$payload = pack("N", $url_id);
file_put_contents("http://m66.net/api/store", $payload);
服務器接收到這個4 字節數據後,可用如下方式解析:
$data = file_get_contents("php://input");
$url_id = unpack("N", $data)[1];
這裡pack("N", $url_id)與unpack("N", $data)正好是一對互補操作。
例如,在實現某種輕量級加密或自定義傳輸協議時,你可能需要把文本信息按字節轉換為數值、做一定的偏移處理後再封裝為二進制:
$text = "Hi!";
$encrypted = "";
for ($i = 0; $i < strlen($text); $i++) {
$encrypted .= pack("C", ord($text[$i]) + 1);
}
// 解密
$decrypted = "";
for ($i = 0; $i < strlen($encrypted); $i++) {
$decrypted .= chr(ord($encrypted[$i]) - 1);
}
echo $decrypted; // 輸出 Hi!