当前位置: 首页> 最新文章列表> 如何避免 mb_strcut 截取时乱码问题

如何避免 mb_strcut 截取时乱码问题

gitbox 2025-05-27

一、为什么 mb_strcut 会出现乱码?

mb_strcut()mb_substr() 不同,它是以为单位进行截取,而非字符。对于 UTF-8 编码的字符串,一个中文字符通常占用 3 个字节,如果你将字符串从中间某个字节位置截断,可能会导致字符不完整,从而在输出时显示乱码或非法字符。

例如:

$str = '你好,世界';
$cut = mb_strcut($str, 0, 4, 'UTF-8');
echo $cut;

这段代码输出的结果很可能是乱码,因为 "你" 这个字在 UTF-8 中占用 3 个字节,mb_strcut 截取了前 4 个字节,刚好把第二个字符 "好" 截断了一部分,造成了乱码。


二、如何避免乱码?

1. 使用 mb_substr 替代

如果你不特别需要字节级控制,推荐使用 mb_substr(),它是基于字符长度而不是字节长度进行操作,更适合处理多字节字符串:

$str = '你好,世界';
$cut = mb_substr($str, 0, 2, 'UTF-8');
echo $cut; // 输出:你好

2. 判断字符边界再截取

如果必须使用 mb_strcut()(例如为了限制存储字节长度),需要结合 mb_strlen() 和字符编码进行更精确控制。可以先用 mb_substr() 获取字符,再用 strlen() 判断是否超出字节长度范围。

function safe_mb_strcut($string, $start, $length, $encoding = 'UTF-8') {
    $substr = '';
    $i = 0;
    $byteCount = 0;

    while ($i < mb_strlen($string, $encoding)) {
        $char = mb_substr($string, $i, 1, $encoding);
        $charLen = strlen($char);
        if ($byteCount + $charLen > $length) {
            break;
        }
        $substr .= $char;
        $byteCount += $charLen;
        $i++;
    }
    return $substr;
}

$str = '你好,世界';
$cut = safe_mb_strcut($str, 0, 6); // 限制总字节数为6
echo $cut; // 输出:你好

三、设置正确的内部编码

在使用 mb_ 系列函数时,务必设定或确认内部字符编码是你预期的(如 UTF-8)。可使用如下方法全局设定:

mb_internal_encoding('UTF-8');

另外,还可通过如下方式检查和调试:

echo mb_detect_encoding($str); // 检查字符串编码

四、实用场景示例:避免URL截断乱码

假设你要截取描述中包含 URL 的部分内容,可以用我们上面的方法安全截取,不破坏 URL。例如:

$str = '更多信息请访问:https://gitbox.net/docs/php-guide.html';
$cut = safe_mb_strcut($str, 0, 40);
echo $cut;

你可以确保输出不会破坏 URL 的结构或引起乱码,特别适用于社交平台摘要、邮件预览等场景。