文本到二进制转换在 PHP 中并没有一个名为 textToBinary 的内置函数,需要根据实际目标选择不同实现。一般来说,需求分为两类:一是生成可读的 0/1 字符串,例如把字母 A 转成 01000001;二是生成真正的二进制字节数据,例如把文本内容写入二进制文件。两种需求对应的函数组合和运行方式并不相同,如果混用,就可能出现乱码或数据错误。本文将分别说明实现方法,并重点介绍如何通过命令行正确运行 PHP 脚本完成转换。

一、生成可读的二进制字符串:ord 与 sprintf 的组合
将单个字符转换为二进制字符串,核心思路是先获取该字符对应的整数编码,再把这个整数格式化为固定长度的二进制表示。对于 ASCII 字符,PHP 的 ord 函数可以返回字符的 ASCII 码值。例如字母 A 的 ASCII 码是 65,接下来只需要把 65 转成二进制。sprintf 函数提供了百分号 b 格式,能够把一个整数直接格式化为二进制字符串,因此最常见的组合就是 ord 加 sprintf。
有一个非常容易忽略的细节是前导零问题。如果直接使用 decbin(ord('A')),得到的结果是 1000001,只有 7 位,丢失了最前面的 0。这在后续还原文本时会带来麻烦,因为二进制长度不固定就难以按 8 位分组。正确做法是使用 sprintf 的百分号 08b 格式,在格式化时强制填充到 8 位,生成 01000001。下面是一个完整示例,把字符串 Hi 转换为用空格分隔的 8 位二进制序列。
<?php
$text = 'Hi';
for ($i = 0; $i < strlen($text); $i++) {
echo sprintf('%08b ', ord($text[$i]));
}
?>这段代码在命令行下运行 php convert.php,会输出 01001000 01101001。这里使用 strlen 按字节遍历,因此它只适用于单字节字符。如果输入包含中文或其他多字节字符,strlen 会把每个字节当成独立字符处理,得到的将是 UTF-8 编码的字节序列,而不是字符对应的 Unicode 码点。对于纯 ASCII 文本的转换需求,这种实现足够简单可靠。
如果不希望结果中包含空格,可以先把每个 8 位二进制存入数组,再用 implode 连接。这样可以避免末尾多余空格,也方便后续存储或传输。无论选择哪种输出形式,保持 8 位宽度都是正确还原数据的前提。生成可读二进制字符串通常用于教学、调试或者某些简单协议的可视化,而不是直接写入二进制文件。
二、生成真正的二进制字节流:pack 与 bin2hex
真正的二进制数据并不是由字符 0 和 1 组成的字符串,而是每个字节直接对应编码值。例如 ASCII 字符 A 在内存中就是一个值为 65 的字节,它本身就是二进制形式。因此,如果只需要把纯文本内容写入二进制文件,直接使用 file_put_contents 写入文本字符串通常就能得到正确结果。但当需求是处理十六进制字符串、按照指定结构打包数据或者强制控制字节格式时,PHP 的 pack 和 bin2hex 函数会更加合适。
bin2hex 函数可以把二进制字符串转换为十六进制表示,pack 函数则能够按照格式字符把十六进制字符串还原为真正的二进制字节。例如把字符串 AB 转换为十六进制后得到 4142,再用 pack 的 H 格式进行打包,就可以生成包含两个字节 0x41 和 0x42 的二进制数据。下面代码演示了文本到十六进制再到二进制字节的完整过程。
<?php
$text = 'AB';
$hex = bin2hex($text);
$binary = pack('H*', $hex);
file_put_contents('binary.dat', $binary);
echo bin2hex($binary) . PHP_EOL;
?>这段代码运行后会输出 4142,并生成一个包含两个字节的文件 binary.dat。需要注意,在 Windows 系统上如果使用 fopen 写入二进制文件,应该使用 wb 模式而不是 w 模式。文本模式可能会把换行符 0x0A 自动转换为 0x0D 0x0A,导致二进制内容被修改。file_put_contents 默认是二进制安全写入,但如果使用 fopen,必须显式指定 wb。
pack 函数支持多种格式字符,其中 C 表示无符号字符,H 表示高半字节在前,h 表示低半字节在前,a 表示以空格填充的字符串。这些格式对协议封装和文件格式处理非常重要。例如要从文本中提取字节数组再打包,可以使用 unpack 加上 C 格式获取每个字节的数值,再通过 call_user_func_array 调用 pack 进行组合。理解这些格式差异,远比记住某个固定写法更有价值。
三、正确运行 PHP 脚本与环境配置
运行 PHP 脚本最常见的方式是命令行模式。在终端执行 php script.php 即可,但前提是 php 可执行文件已经加入系统 PATH。Windows 用户可能需要使用完整路径,例如 C:phpphp.exe script.php。Linux 和 macOS 可以使用 which php 命令检查 PHP 是否可用。脚本文件建议保存为 UTF-8 无 BOM 编码,因为 BOM 头会被 PHP 当作输出内容的一部分,可能导致转换结果开头多出几个不可见字节。
如果在命令行中直接输出真正的二进制数据,终端可能会把这些字节解释为控制字符,造成显示乱码甚至光标乱跳。这并不意味着数据错误,而是终端渲染机制带来的干扰。更可靠的做法是把二进制结果写入文件,然后使用 bin2hex 或外部工具检查文件内容。对于可读的 0/1 字符串,直接输出到标准输出通常没有问题,但最好使用 fwrite 指定 STDOUT,避免多余换行影响结果。
多字节字符处理是另一个容易混淆的地方。以中文“你”为例,它在 UTF-8 编码下占三个字节,如果按字节转换二进制,得到的是 E4 BD A0 对应的二进制序列,而不是 Unicode 码点 4F60 对应的二进制。若需求是获取 Unicode 码点的二进制表示,可以借助 mb_ord 函数获取码点,再使用 sprintf 格式化。下面示例展示了这两种不同目标下的写法差异。
<?php
$char = '你';
$bytes = unpack('C*', $char);
foreach ($bytes as $byte) {
echo str_pad(decbin($byte), 8, '0', STR_PAD_LEFT) . ' ';
}
echo PHP_EOL;
if (function_exists('mb_ord')) {
$codepoint = mb_ord($char, 'UTF-8');
echo str_pad(decbin($codepoint), 16, '0', STR_PAD_LEFT) . PHP_EOL;
}
?>这个例子先按 UTF-8 字节输出三个 8 位二进制组,再输出 16 位 Unicode 码点二进制表示。两种结果都正确,但适用场景完全不同。涉及多字节文本时,务必先确认自己需要的是编码后的字节序列,还是字符本身的码点值,否则很容易在后续处理中出现乱码或数据错位。
四、常见错误与调试方法
第一个常见误区是尝试使用 sprintf('%b', $text) 把整个字符串一次性转换为二进制。sprintf 的百分号 b 只接受整数,传入字符串会被转换为整数 0,最终输出也是 0,完全不符合预期。第二个误区是忽略前导零,导致二进制字符串长度不固定。若希望后续按 8 位还原,必须保证每一位都完整,使用 str_pad 或 sprintf 的填充功能可以避免这个问题。
第三个常见问题出现在文件写入环节。Windows 系统中,fopen 的默认文本模式会自动转换换行符,如果写入二进制数据时仍然使用 w 模式,文件内容可能被悄悄修改。解决方式是使用 wb 模式打开文件。第四个问题与调试有关:直接 echo 二进制数据很难判断内容是否正确,应优先使用 bin2hex 打印十六进制,或者用 var_dump 查看字符串长度,还可以在命令行使用 xxd 或 od -x 检查生成的文件。
调试脚本时,建议在开头设置 error_reporting(E_ALL) 和 ini_set('display_errors', '1'),让所有错误和警告都能直接显示。这样可以及时捕获未定义函数、参数类型错误等问题。对于多字节函数如 mb_ord,还要确认 mbstring 扩展已启用。掌握这些调试手段之后,再根据具体需求选择 ord 加 sprintf 或 pack 加 bin2hex 的方案,就能稳定完成 PHP 文本到二进制的转换任务。