PHP 中使用 strlen() 和数组下标遍历 UTF-8 编码的含重音字符(如 á)字符串时,会因字节切分导致乱码;根本原因是 strlen() 按字节计数,而多字节字符被错误截断。
php
中使用 `strlen()` 和数组下标遍历 utf-8 编码的含重音字符(如 `á`)字符串时,会因字节切分导致乱码;根本原因是 `strlen()` 按字节计数,而多字节字符被错误截断。
在 UTF-8 编码中,普通 ASCII 字符(如 a、l)占 1 字节,但带重音的字符(如 á)通常由 2 个字节组成(0xC3 0xA1)。当使用 $text[$d] 访问字符串时,PHP 实际上是按
字节索引
操作——而非按 Unicode 字符(code point)索引。因此,循环中:
执行过程如下:
strlen("ála") 返回 4(á 占 2 字节 + l + a 各 1 字节);
$text[0] 取第 1 字节 0xC3 → 无效 UTF-8 单字节,浏览器渲染为 ;
$text[1] 取第 2 字节 0xA1 → 同样无效,显示为 ;
$text[2] 取 l → 正常;
$text[3] 取 a → 正常;
结果即:
l
a。 ✅ 正确解法:使用多字节安全函数 推荐使用 mb_str_split()(PHP ≥ 7.4,需启用 mbstring 扩展): 立即学习 “ PHP免费学习笔记(深入) ”; PHP 8.5.5 PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。 下载
⚠️ 若环境不支持 mb_str_split()(如 PHP < 7.4),可改用 preg_split() 安全分割 Unicode 字符:
?
关键注意事项:
始终确保脚本文件保存为 UTF-8 无 BOM 格式;
在 HTML 头部声明编码:;
输出非 ASCII 内容前建议用 htmlspecialchars($str, ENT_QUOTES, 'UTF-8') 防止转义异常;
避免对 UTF-8 字符串使用 strlen()/substr()/$str[$i] 等单字节函数——应统一替换为 mb_strlen()、mb_substr()、mb_substr($str, $i, 1) 等多字节对应函数。
从根本上说,这不是“奇怪的结果”,而是 UTF-8 多字节特性与单字节操作不兼容的必然表现。尊重字符编码语义,才能写出健壮的国际化 PHP 代码。
$text = "ála";
for ($d = 0; $d < strlen($text); $d++) {
echo $text[$d] . "
";
}l
a。 ✅ 正确解法:使用多字节安全函数 推荐使用 mb_str_split()(PHP ≥ 7.4,需启用 mbstring 扩展): 立即学习 “ PHP免费学习笔记(深入) ”; PHP 8.5.5 PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。 下载
$text = "ála";
$chars = mb_str_split($text, 1, 'UTF-8');
foreach ($chars as $char) {
echo htmlspecialchars($char, ENT_QUOTES, 'UTF-8') . "
";
}
// 输出:á
l
a(正确)$text = "ála";
$chars = preg_split('//u', $text, -1, PREG_SPLIT_NO_EMPTY);
foreach ($chars as $char) {
echo htmlspecialchars($char, ENT_QUOTES, 'UTF-8') . "
";
}