PHP中文字符串截断无乱码解决方法
一个比较好用的字符串截取函数:
functionsubstring($str,$start,$length){//比较好用字符串截取函数
$len=$length;
if($length<0){
$str=strrev($str);
$len=-$length;
}
$len=($len<strlen($str))?$len:strlen($str);
$tmpstr="";
for($i=$start;$i<$len;$i++)
{
if(ord(substr($str,$i,1))>0xa0)
{
$tmpstr.=substr($str,$i,2);
$i++;
}else{
$tmpstr.=substr($str,$i,1);
}
}
if($length<0)$tmpstr=strrev($tmpstr);
return$tmpstr;
}
使用方法示例:
$str1='我是一串比较长的中文不带英文'; $str2='我是一串比较长的中文带yingwen'; $len=strlen($str1); echo'<br/>'.$len;//return28 $len=strlen($str2); echo'<br/>'.$len;//return29 echo'<br/>'; echosubstring($str1,0,11); echo'<br/>'; echosubstring($str2,0,11); echo'<br/>'; echosubstring($str1,16,28); echo'<br/>'; echosubstring($str2,16,29);
结果显示:
28
29
我是一串比较
我是一串比较
中文不带英文
中文带yingwen
这个函数十分有用,比如用来截断比较长的文件名,但是要在中间加上...,可以这样来做:
functionformatName($str,$size){
$len=strlen($str);
if(strlen($str)>$size){
$part1=substring($str,0,$size/2);
$part2=substring($str,$len-($size/2),$len);
return$part1."...".$part2;
}else{
return$str;
}
}
另外,网上看到一种超级简单的中文截断解决方案,试用了一下,效果也不错:
echosubstr($str1,0,10).chr(0);
原理解释:
chr(0)不是null
07null是什么都没有,而chr(0)的值是0。表示成16进制是0x00,表示成二进制是00000000
08虽然chr(0)不会显示出什么,但是他是一个字符。
09当汉字被截断时,根据编码规则他总是要把后边的其他字符拉过来一起作为汉字解释,这就是出现乱码的原因。而值为0x81到0xff与0x00组合始终都显示为“空”
10根据这一特点,在substr的结果后面补上一个chr(0),就可以防止出现乱码了
----------------------------
20120705更新:
以上方法虽好,但是偶尔还是会碰到乱码,原因未深究。不过可以用以下的方法,对UTF8字符文本屡试不爽。
注意:该方法中将汉字计算为1单位长度,英文一个字母1单位长度,所以截断时需要注意长度设置。
计算长度的方法:
functionstrlen_UTF8($str)
{
$len=strlen($str);
$n=0;
for($i=0;$i<$len;$i++){
$x=substr($str,$i,1);
$a=base_convert(ord($x),10,2);
$a=substr('00000000'.$a,-8);
if(substr($a,0,1)==0){
}elseif(substr($a,0,3)==110){
$i+=1;
}elseif(substr($a,0,4)==1110){
$i+=2;
}
$n++;
}
return$n;
}//Endstrlen_UTF8;
字符串截断函数:
functionsubString_UTF8($str,$start,$lenth)
{
$len=strlen($str);
$r=array();
$n=0;
$m=0;
for($i=0;$i<$len;$i++){
$x=substr($str,$i,1);
$a=base_convert(ord($x),10,2);
$a=substr('00000000'.$a,-8);
if($n<$start){
if(substr($a,0,1)==0){
}elseif(substr($a,0,3)==110){
$i+=1;
}elseif(substr($a,0,4)==1110){
$i+=2;
}
$n++;
}else{
if(substr($a,0,1)==0){
$r[]=substr($str,$i,1);
}elseif(substr($a,0,3)==110){
$r[]=substr($str,$i,2);
$i+=1;
}elseif(substr($a,0,4)==1110){
$r[]=substr($str,$i,3);
$i+=2;
}else{
$r[]='';
}
if(++$m>=$lenth){
break;
}
}
}
returnjoin($r);
}//EndsubString_UTF8;
使用方法和之前介绍的一样,比如formatName可以实现如下(这对汉字长度做了小优化):
functionformatName($str,$size){
$len=strlen_UTF8($str);
$one_len=strlen($str);
$size=$size*1.5*$len/($one_len);
if(strlen_UTF8($str)>$size){
$part1=subString_UTF8($str,0,$size/2);
$part2=subString_UTF8($str,$len-($size/2),$len);
return$part1."...".$part2;
}else{
return$str;
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。