原文地址:实现中文字串截取无乱码的方法
作者:肖岩
UTF-8中文截取函数
在PHP中,substr()函数截取带有中文字符串的话,可能会出现乱码,这是因为中西文一个字节所占有的字节数不一样,而substr的长度参数是按照字节去算的,在GB2312编码时,一个中文占2个字节,英文为1个字节,而在UTF-8编码当中,一个中文可能占有2个或3个字节,英文或半角标点占1字节。
解决方法
UTF-8编码的字符可能由1-3个字节组成,具体数目可以由第一个字节判断出来。
第一个字节大于224的,它与它之后的2个字节一起组成一个UTF-8字符
第一个字节大于192小于224的,它与它之后的1个字节组成一个UTF-8字符,否则第一个字节本身就是一个英文字符(包括数字和一小部分标点符号)。
<?php
$a="我是程序员";
class Dx
{
private $str;
public function msubstr($string,$start,$length)
{
if(strlen($string)>$length)
{
$n=0;
$str="";
$len=$start+$length;
for($i=$start;$i<$len;$i++)
{
if(ord(substr($string,$n,1))>224)
{
$str.=substr($string,$n,3);
$n+=3;
$i++;
}
elseif(ord(substr($string,$n,1))>192)
{
$str.=substr($string,$n,2);
$i++;
}
else
{
$str.=substr($string,$n,1);
}
}
return $str;
}
else
{
return $string;
}
}
public function msub($string,$start,$length)
{
if(strlen($string)>$length)
{
$str="";
$len=$start+$length;
for($i=$start;$i<$len;$i++)
{
if(ord(substr($string,$i,1))>0xa0)
{
$str.=substr($string,$i,2);
$i++;
}
else
{
$str.=substr($string,$i,1);
}
}
return $str;
}
else
{
return $string;
}
}
}
$sub = new Dx();
echo $sub->msubstr($a,0,8);//我是程序
?>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
除了上面的方法,还可以使用mb_substr来解决,代码如下:
<?php
$a="wo的name是中国!";
echo mb_substr($a,0,9,'UTF-8');//wo的name是中
echo substr($a,0,15);//wo的name是中
?>
在PHP中,substr()函数截取带有中文字符串的话,可能会出现乱码,这是因为中西文一个字节所占有的字节数不一样,而substr的长度参数是按照字节去算的,在GB2312编码时,一个中文占2个字节,英文为1个字节,而在UTF-8编码当中,一个中文可能占有2个或3个字节,英文或半角标点占1字节。
解决方法
UTF-8编码的字符可能由1-3个字节组成,具体数目可以由第一个字节判断出来。
第一个字节大于224的,它与它之后的2个字节一起组成一个UTF-8字符
第一个字节大于192小于224的,它与它之后的1个字节组成一个UTF-8字符,否则第一个字节本身就是一个英文字符(包括数字和一小部分标点符号)。
<?php
$a="我是程序员";
class Dx
{
}
$sub = new Dx();
echo $sub->msubstr($a,0,8);//我是程序
?>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
除了上面的方法,还可以使用mb_substr来解决,代码如下:
<?php
$a="wo的name是中国!";
echo mb_substr($a,0,9,'UTF-8');//wo的name是中
echo substr($a,0,15);//wo的name是中
?>
十八哥版 通过字符截取
<?php
header("Content-type:text/html;charset=utf-8");
$str='中华人aaa民cc共和ee国wwww';
function utf8sub($str,$len){
if($len<=0){
return '';
}
$length=strlen($str);
$offset=0; //截取高位字节时的偏移量
$chars=0; //截取到的字符数
$res=''; //截取到的字符串
while($chars< $len &&$offset<=$length){//只要还没截取到$len 的长度,旧继续进行
$high =decbin(ord(substr($str,$offset,1)));
if(strlen($high)<8){
//截取一个字节
$count=1;
}else if(substr($high,0,3)=='110'){
//截取2个字节
$count=2;
}else if (substr($high,0,4)=='1110'){
//截取3个
$count=3;
}else if(substr($high,0,5)=='11110'){
//截取4个
$count=4;
}else if(substr($high,0,6)=='111110'){
//截取5个
$count=5;
}else if(substr($high,0,7)=='1111110'){
//截取6个
$count=6;
}
$res .=substr($str,$offset,$count);
$chars += 1;
$offset += $count;
}
return $res;
//print_r($res);
}
echo utf8sub($str,5);
?>