在 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() 的配合使用。