chunk_split 是 PHP 中按字节而非字符切分字符串的函数,不识别 UTF-8 多字节、不考虑语义边界,易致中文或 emoji 乱码;其 $length 按字节计,$separator 无条件追加至每块末尾(含最后一块),需手动 rtrim 清理。

chunk_split 是 PHP 里一个“只管切、不管语义”的字符串分割函数,它按固定字节数切分,不识别 UTF-8 多字节字符、不考虑单词边界、也不处理换行逻辑。用对了很顺手,用错了会在中文或 emoji 场景下直接截断字节,导致乱码。
chunk_split 的参数行为和默认值
它的签名是 chunk_split(string $string, int $length = 76, string $separator = "\r\n")。注意三点:
-
$length按**字节**计数,不是字符 —— 这意味着"你好"(UTF-8 下占 6 字节)在chunk_split($str, 2)中会被切成"你"、"好"这类无效序列 -
$separator会**无条件追加到每一块末尾**,包括最后一块 —— 所以输出末尾总多一个\r\n,需手动rtrim($result, "\r\n")清理(尤其用于 HTTP header 或 base64 封装时) - 不修改原字符串,总是返回新字符串;输入为空串或
null会返回空串,不会报错
base64_encode 后必须用 chunk_split 吗?
不是“必须”,但 RFC 2045 要求 base64 编码后的数据每行不超过 76 字符,并以 \r\n 分隔。PHP 的 base64_encode() 本身不加换行,所以常见写法是:
$raw = "Hello 世界"; $encoded = base64_encode($raw); // "SGVsbG8g5L2g5aW9" $wrapped = chunk_split($encoded); // 自动按 76 字节 + \r\n
但要注意:如果原始数据极短(比如 chunk_split 仍会加一次 \r\n,所以实际发邮件或构造 MIME body 时,建议显式控制:
立即学习“PHP免费学习笔记(深入)”;
- 用
chunk_split($encoded, 76, "\r\n")明确长度和分隔符 - 后续用
rtrim($wrapped, "\r\n")去掉末尾多余换行 - 若需严格符合 RFC(如最后一行不足 76 字符不强制换行),
chunk_split不够用,得手写循环或改用wordwrap($encoded, 76, "\r\n", true)
处理中文/emoji 时 chunk_split 为什么出错?
因为它是字节级函数,而 UTF-8 中一个汉字占 3 字节、一个 emoji 可能占 4 字节。当 $length 设为 2 或 5 这类非 3/4 倍数时,大概率卡在中间字节上。
例如:chunk_split("?a", 2) 输出可能是 "a" + \r\n —— 第一个块只有 emoji 的前 2 字节,无法解码。
- 解决办法一:改用
mb_substr循环切分(兼容 UTF-8) - 解决办法二:先用
mb_convert_encoding($str, 'ISO-8859-1', 'UTF-8')强转单字节编码(仅限纯 ASCII + 拉丁字符) - 解决办法三:用正则
preg_replace('/(.{' . $len . '})/u', '$1' . $sep, $str),配合u修饰符按 Unicode 字符切(但性能较差,长文本慎用)
真正需要按“字符”而非“字节”切分时,chunk_split 就不该出现在方案里 —— 它的设计目标从来就不是多字节安全,而是快速满足 base64 行宽这类协议需求。



















