
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)索引。因此,循环中:
$text = "ála";
for ($d = 0; $d < strlen($text); $d++) {
echo $text[$d] . "<br>";
}执行过程如下:
- strlen("ála") 返回 4(á 占 2 字节 + l + a 各 1 字节);
- $text[0] 取第 1 字节 0xC3 → 无效 UTF-8 单字节,浏览器渲染为 ;
- $text[1] 取第 2 字节 0xA1 → 同样无效,显示为 ;
- $text[2] 取 l → 正常;
- $text[3] 取 a → 正常;
结果即:<br><br>l<br>a。
✅ 正确解法:使用多字节安全函数
推荐使用 mb_str_split()(PHP ≥ 7.4,需启用 mbstring 扩展):
立即学习“PHP免费学习笔记(深入)”;
$text = "ála";
$chars = mb_str_split($text, 1, 'UTF-8');
foreach ($chars as $char) {
echo htmlspecialchars($char, ENT_QUOTES, 'UTF-8') . "<br>";
}
// 输出:á<br>l<br>a(正确)⚠️ 若环境不支持 mb_str_split()(如 PHP < 7.4),可改用 preg_split() 安全分割 Unicode 字符:
$text = "ála";
$chars = preg_split('//u', $text, -1, PREG_SPLIT_NO_EMPTY);
foreach ($chars as $char) {
echo htmlspecialchars($char, ENT_QUOTES, 'UTF-8') . "<br>";
}? 关键注意事项:
- 始终确保脚本文件保存为 UTF-8 无 BOM 格式;
- 在 HTML 头部声明编码:<meta charset="UTF-8">;
- 输出非 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 代码。



















