在PHP 中, pack()函數用於將數據按照指定格式打包成二進製字符串,常用於底層數據處理、網絡通信協議、文件格式解析等場景。為了更好地理解和調試pack()打包後的二進制數據,通常需要用類似hexdump的方式查看其具體的字節結構。
本文將介紹如何在PHP 中實現一個簡單的hexdump()函數,並配合pack()函數查看打包後的二進制內容。
pack()函數的語法是:
string pack(string $format, mixed ...$values)
$format指定數據的打包格式,比如'C'表示無符號字符(1字節), 'n'表示16位無符號短整數(網絡字節序), 'V'表示32位無符號長整數(小端字節序)等。
$values是要打包的值列表。
例如:
$bin = pack('Cnv', 0x12, 0x3456, 0x789a);
這條語句會生成一個二進製字符串,其中依次包含:
1 字節:0x12
2 字節(網絡序,big-endian):0x3456
2 字節(小端序,little-endian):0x789a
下面是一個簡單的hexdump()函數,用來將二進製字符串按字節輸出十六進製表示,並附帶對應的ASCII 字符:
function hexdump(string $data): void {
$len = strlen($data);
$offset = 0;
while ($offset < $len) {
// 每行顯示16位元組
$chunk = substr($data, $offset, 16);
$hex = '';
$ascii = '';
for ($i = 0; $i < strlen($chunk); $i++) {
$byte = ord($chunk[$i]);
$hex .= sprintf("%02X ", $byte);
// 可打印字符顯示原字符,否則顯示點號
$ascii .= ($byte >= 32 && $byte <= 126) ? $chunk[$i] : '.';
}
// 補齊不足16位元組时的空格
$hex = str_pad($hex, 16 * 3);
// 輸出格式:偏移地址 + 十六進位 + ASCII
printf("%08X %s %s\n", $offset, $hex, $ascii);
$offset += 16;
}
}
假設我們要用pack()函數打包幾個數據,並用hexdump()查看:
<?php
// 打包數據:1位元組无符号字符,2位元組网络序,4位元組小端序
$binary = pack('C n V', 0x41, 0x4243, 0x44454647);
hexdump($binary);
?>
執行後,輸出如下:
00000000 41 42 43 47 46 45 44 00 00 00 00 00 00 00 00 00 ABCGFED..........
解析:
0x41是字符'A'
0x4243按網絡字節序存儲為42 43 ('B' 'C')
0x44454647按小端序存儲為47 46 45 44 (對應ASCII 'G' 'F' 'E' 'D')
pack()函數的格式字符串非常強大,詳細格式請查閱官方文檔,如m66.net/manual/en/function.pack.php 。
hexdump()的實現可以根據需求調整,比如支持更多格式、顯示更多註釋等。
二進制數據中非可打印字符無法直觀看懂,借助hexdump()可以方便調試。
通過以上方法,開發者能夠直觀地觀察pack()打包後的二進制結構,有助於調試和理解數據格式。希望本文能幫你快速上手hexdump()和pack()的配合使用。