当前位置: 首页> 最新文章列表> pack() 与 ord() 的互补使用

pack() 与 ord() 的互补使用

M66 2025-06-06

1. pack() 的基本用法

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

这个过程就像是将一个整数数组转换为一个压缩后的二进制字符串。


2. ord() 的基本用法

pack() 相反,ord() 用于将字符转换成其对应的 ASCII 或 Unicode 值。它是 pack() 的“解码器”,在从二进制字符串中提取数据时非常有用。

例如:

$char = "A";
$ascii = ord($char); // 返回 65

这个函数非常适合与 pack() 配合,从编码后的字符串中逐字节恢复原始数据。


3. 两者的互补关系

将数据编码为二进制时用 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) 正好是一对互补操作。


4. 实战场景举例

例如,在实现某种轻量级加密或自定义传输协议时,你可能需要把文本信息按字节转换为数值、做一定的偏移处理后再封装为二进制:

$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!

这个例子中 ord() 将字符变为数字,pack() 封装为二进制,解密过程则用 ord() 还原后再偏移。