在PHP中,substr()函数截取带有中文字符串的话,可能会出现乱码,这是因为中西文一个字节所占有的字节数不一样,而substr()的长度参数是按照字节去算的。substr()截取位数不准确,substr()硬生生地将一个中文字符“锯”成两半,造成断开的字符会把其后的码位拉过来一起做一个字,所以出现了PHP substr()截取中文乱码现象。
在GB2312编码时,一个中文占2个字节,英文为1个字节,而在UTF-8编码当中,一个中文可能占有2个或3个字节,英文或半角标点占1字节。
0. 原生解决方案
PHP中有原生的解决方案,mb_substr()方法。需要开启mbstring扩展,方法:
在php的配置文件中,寻找到extension=php_mbstring.dll,确保扩展被加载——此行首无分号。
下面重点讲使用基本函数substr去实现中文字符串的截取。
1. 基于substr()解决方案
1.1解决思路:
UTF-8编码的字符可能由1-3个字节组成,具体数目可以由第一个字节判断出来。
第一个字节大于224的,它与它之后的2个字节一起组成一个UTF-8字符
第一个字节大于192小于224的,它与它之后的1个字节组成一个UTF-8字符,否则第一个字节本身就是一个英文字符(包括数字和一小部分标点符号)。
1.2 substr()语法
substr()中文文档
string substr ( string $string , int $start [, int $length ] )
参数
string
输入字符串。必须至少有一个字符。
start
如果 start 是非负数,返回的字符串将从 string 的 start 位置开始,从 0 开始计算。
如果 start 是负数,返回的字符串将从 string 结尾处向前数第 start 个字符开始。
如果 string 的长度小于 start ,将返回 FALSE 。
length
如果提供了正数的 length,返回的字符串将从 start 处开始最多包括 length 个字符(取决于 string 的长度)。
如果提供了负数的 length ,那么 string 末尾处的 length 个字符将会被省略(若 start 是负数则从字符串尾部算起)。
如果 start 不在这段文本中,那么将返回 FALSE 。
如果提供了值为 0 ,FALSE 或 NULL 的 length,那么将返回一个空字符串。
如果没有提供 length,返回的子字符串将从 start 位置开始直到字符串结尾。
返回值
返回提取的子字符串, 或者在失败时返回 **FALSE
**。
1.3 myGBsubstr()
function myGBsubstr($string, $start, $length) {
if (strlen($string) > $length) {
$str = null;
$len = 0;
$i = $start;
while ( $len < $length) {
if (ord(substr($string, $i, 1)) > 0xc0) {
$str .=substr($string, $i, 3);
$i+= 3;
}elseif (ord(substr($string, $i, 1)) > 0xa0) {
$str .= substr($string, $i, 2);
$i+= 2;
}else {
$str.=substr($string, $i, 1);
$i++;
}
$len ++;
}
return $str;
}else {
return $string;
}
}
1.4 优化
判断mbstring模块是否可用,如果可用使用原生的mb_substr()函数,反之,使用自己定义的中文字符串截取函数。
function GBsubstr($string, $start,$length) {
if (!function_exists(mb_substr)) {
myGBsubstr($string, $start, $length);
} else {
mb_substr($string, $start, $length, 'utf8');
}
}
网友评论