You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP 8.1+中mb_convert_encoding处理UTF-16转UTF-8时出现多余问号问题

PHP 8.1+ mb_convert_encoding UTF-16转UTF-8多出问号的解决方法

问题重现

我在更新PHP应用时遇到异常:应用导入Google Keyword Planner的UTF-16编码CSV文件,转成UTF-8后,PHP 8.1及以上版本会在结果末尾多出一个问号,旧版本(7.4、8.0)则正常。测试代码如下:

var_dump(mb_convert_encoding("\0008\0008\0000\000", "UTF-8", "UTF-16"));

// PHP 8.1.3 - 8.1.13、8.2.0版本输出:
// string(4) "880?"

// PHP 7.4.32、8.0.8 - 8.0.26版本输出:
// string(3) "880"

原因分析

问题核心是PHP 8.1对mbstring扩展错误处理行为的变更:

  • 旧版本(7.4、8.0)遇到不完整的UTF-16字节序列(比如奇数长度的输入,最后一个字节无法组成完整的UTF-16字符)时,会直接忽略这部分无效内容。
  • PHP 8.1及以上版本默认将错误处理模式设为"replace",遇到无效或不完整的多字节序列时,会用替换字符?代替,而非丢弃。

你的测试输入总长度为奇数,最后一个字节无法构成完整的UTF-16字符,属于无效序列,因此新版本会自动补上问号。

解决方案

方案1:确保输入为完整的UTF-16序列

UTF-16每个字符占用2或4字节,输入必须是偶数长度。处理时先检查长度,截断奇数长度的最后一个字节:

$utf16Input = "\0008\0008\0000\000";
// 确保字节数为偶数
if (strlen($utf16Input) % 2 !== 0) {
    $utf16Input = substr($utf16Input, 0, -1);
}
$utf8Output = mb_convert_encoding($utf16Input, "UTF-8", "UTF-16");
var_dump($utf8Output); // 输出 string(3) "880"

方案2:显式设置错误处理模式为ignore

调用mb_convert_encoding时,第四个参数指定错误处理为"ignore",直接忽略无效或不完整的序列:

$utf8Output = mb_convert_encoding("\0008\0008\0000\000", "UTF-8", "UTF-16", "ignore");
var_dump($utf8Output); // 输出 string(3) "880"

额外提示:明确UTF-16字节序

Google Keyword Planner的CSV通常是UTF-16LE(小端)编码,建议转换时明确指定"UTF-16LE"而非通用的"UTF-16",避免字节序自动检测可能带来的问题:

$utf8Output = mb_convert_encoding($utf16Input, "UTF-8", "UTF-16LE", "ignore");

内容的提问来源于stack exchange,提问作者Daniel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 18:35:51