多字节字符串处理(MBString)
处理中文等多字节字符时,必须使用 MBString 扩展,否则会出现乱码或截断问题。
为什么要用 MB 函数
php
$str = "中文字符串";
echo strlen($str); // 15(UTF-8 下每个中文3字节)
echo mb_strlen($str); // 5(正确字符数)
echo substr($str, 0, 3); // 乱码(截断了字节)
echo mb_substr($str, 0, 3); // 中文(正确截取3个字符)常用函数对比
| 单字节函数 | 多字节函数 | 说明 |
|---|---|---|
| strlen() | mb_strlen() | 字符串长度 |
| substr() | mb_substr() | 截取子串 |
| strpos() | mb_strpos() | 查找位置 |
| strrpos() | mb_strrpos() | 反向查找 |
| strtolower() | mb_strtolower() | 转小写 |
| strtoupper() | mb_strtoupper() | 转大写 |
| substr_count() | mb_substr_count() | 子串出现次数 |
基础用法
php
// 设置内部编码
mb_internal_encoding('UTF-8');
$str = "Hello 世界";
// 获取长度
echo mb_strlen($str); // 8
echo mb_strlen($str, 'UTF-8'); // 显式指定编码
// 截取字符串
echo mb_substr($str, 6, 2); // 世界
// 查找位置
echo mb_strpos($str, '世界'); // 6
// 大小写转换(支持中文拼音规则)
echo mb_strtoupper('hello'); // HELLO
// 分割字符串(类似 explode)
$chars = mb_str_split('中文测试', 1); // ['中', '文', '测', '试']编码转换
php
// 转换编码
$gbk = mb_convert_encoding("中文", 'GBK', 'UTF-8');
$utf8 = mb_convert_encoding($gbk, 'UTF-8', 'GBK');
// 自动检测编码
$encoding = mb_detect_encoding($str, ['UTF-8', 'GBK', 'ISO-8859-1']);
echo $encoding;
// 批量转换数组
$arr = ['中', '文'];
$converted = array_map(function($s) {
return mb_convert_encoding($s, 'GBK', 'UTF-8');
}, $arr);实用的中文处理函数
php
// 截取中文摘要(不截断字符)
function excerpt($text, $length = 100) {
if (mb_strlen($text) <= $length) {
return $text;
}
return mb_substr($text, 0, $length) . '...';
}
// 计算中英文混合的实际宽度(中文算2字符宽)
function mb_strwidth_cn($str) {
$width = 0;
for ($i = 0; $i < mb_strlen($str); $i++) {
$char = mb_substr($str, $i, 1);
// CJK 字符宽度为2
$width += (preg_match('/[\x{4e00}-\x{9fa5}]/u', $char)) ? 2 : 1;
}
return $width;
}
// 按宽度截取(用于等宽字体对齐)
function mb_strimwidth_cn($str, $width) {
$result = '';
$currentWidth = 0;
for ($i = 0; $i < mb_strlen($str); $i++) {
$char = mb_substr($str, $i, 1);
$charWidth = (preg_match('/[\x{4e00}-\x{9fa5}]/u', $char)) ? 2 : 1;
if ($currentWidth + $charWidth > $width) {
break;
}
$result .= $char;
$currentWidth += $charWidth;
}
return $result;
}正则表达式中的中文
php
// 匹配中文字符
preg_match('/[\x{4e00}-\x{9fa5}]+/u', '中文abc', $matches);
// 提取所有中文
preg_match_all('/[\x{4e00}-\x{9fa5}]/u', 'Hello 中文', $matches);
print_r($matches[0]); // ['中', '文']
// 替换中文
$text = preg_replace('/[\x{4e00}-\x{9fa5}]+/u', '[中文]', '这是中文测试');
echo $text; // [中文]注意事项
- 始终设置
mb_internal_encoding('UTF-8') - 数据库连接也要使用 UTF-8
- HTML 页面头部声明
<meta charset="UTF-8"> - 处理文件名等系统接口时可能需要转码