php截取中文问题
前续:本文来自于网络文章整理,仅供参考,欢迎纠错指正。
在PHP程序开发过程中,经常会执行字符串的截取操作,比如输出信息列表时,标题不宜过长,打印文章摘要时,也要执行一系列的字符串截取操作。
php函数:
1、substr截取中文时经常会出现乱码,因为utf-8下汉字是3字节的,如果截取长度正好是3的倍数应该不会出现乱码,可是如果你要截取的字符串中有空格,或者其他字符(比如 “ ”),也会出现乱码。
注意:substr按字节截取
还有人指出:substr($str, 0, 30).chr(0);//可以防止中文乱码
chr(0)不是null ,null是什么都没有,而chr(0)的值是0。表示成16进制是0x00,表示成二进制是00000000 ,虽然chr(0)不会显示出什么,但是他是一个字符。 当汉字被截断时,根据编码规则他总是要把后边的其他字符拉过来一起作为汉字解释,这就是出现乱码的原因。而值为0x81到0xff与0x00组合始终都显示为“空” 根据这一特点,在substr的结果后面补上一个chr(0),就可以防止出现乱码了。(但亲身试了一下好像没效果)
2、使用mbstring扩展库的mb_substr和mb_strcut截取就不会出现乱码了,需要在php.ini中打开php_mbstring.dll。
注意:mb_substr 按字符截取,而mb_strcut() 按字节数截取
3、PHP5开始,iconv_substr函数随之出现。
注意:iconv_substr按字符截取
4、自定义函数,都大同小异,效率不高。
函数的核心关键在于 通过判断 截多少个字节上
下面是搜罗来的一些方法:
方法一:
1 function cut_substr($string, $beginIndex, $length){ 2 if(strlen($string) < $length){ 3 return substr($string, $beginIndex); 4 } 5 //ord() 函数返回字符串的首个字符的 ASCII 值 6 $char = ord($string[$beginIndex + $length - 1]); 7 if($char >= 224 && $char <= 239){ 8 $str = substr($string, $beginIndex, $length - 1); 9 return $str; 10 } 11 12 $char = ord($string[$beginIndex + $length - 2]); 13 if($char >= 224 && $char <= 239){ 14 $str = substr($string, $beginIndex, $length - 2); 15 return $str; 16 } 17 18 return substr($string, $beginIndex, $length); 19 }
方法二:
1 function utf8_substr($str,$len){ 2 if($len<0){ 3 return ''; 4 } 5 $res = ''; 6 $offset = 0; 7 $chars = 0; 8 $count = 0; 9 $length = strlen($str);//待截取字符串的字节数 10 while($chars<$len && $offset<$length){ 11 $high = decbin(ord(substr($str,$offset,1)));//先截取客串的一个字节,substr按字节进行截取 12 //重要突破,已经能够判断高位字节 13 if(strlen($high)<8){//英文字符ascii编码长度为7,通过长度小于8来判断 14 $count = 1; // echo 'hello,I am in','<br>'; 15 }elseif (substr($high,0,3) == '110') { 16 $count = 2; //取两个字节的长度 17 }elseif (substr($high,0,4) == '1110') { 18 $count = 3; //取三个字节的长度 19 }elseif (substr($high,0,5) == '11110') { 20 $count = 4; 21 22 }elseif (substr($high,0,6) == '111110') { 23 $count = 5; 24 }elseif(substr($high,0,7)=='1111110'){ 25 $count = 6; 26 } 27 $res .= substr($str,$offset,$count); 28 $chars +=1; 29 $offset += $count; 30 } 31 return $res; 32 }
方法三:
1 function substr_UTF8($str, $start, $lenth){ 2 $len = strlen($str); 3 $r = array(); 4 $n = 0; 5 $m = 0; 6 for($i = 0; $i < $len; $i++) { 7 $x = substr($str, $i, 1); 8 $a = base_convert(ord($x), 10, 2); 9 $a = substr('00000000'.$a, -8); 10 if ($n<$start){ 11 if (substr($a, 0, 1) == 0) { 12 }elseif (substr($a, 0, 3) == 110) { 13 $i += 1; 14 }elseif (substr($a, 0, 4) == 1110) { 15 $i += 2; 16 } 17 $n++; 18 }else{ 19 if (substr($a, 0, 1) == 0) { 20 $r[] = substr($str, $i, 1); 21 }elseif (substr($a, 0, 3) == 110) { 22 $r[] = substr($str, $i, 2); 23 $i += 1; 24 }elseif (substr($a, 0, 4) == 1110) { 25 $r[] = substr($str, $i, 3); 26 $i += 2; 27 }else{ 28 $r[] = ''; 29 } 30 if (++$m >= $lenth){ 31 break; 32 } 33 } 34 } 35 if (is_array($r)) { 36 return implode('',$r); 37 } 38 return $str; 39 }
方法四:
1 //字符串编码为UTF-8的,一个中文字符占三个字节 2 function chinesesubstr($str, $start, $len) { // $str指字符串,$start指字符串的起始位置,$len指字符串长度 3 $strlen = $start + $len; // 用$strlen存储字符串的总长度,即从字符串的起始位置到字符串的总长度 4 for($i = $start; $i < $strlen;) { 5 if (ord ( substr ( $str, $i, 1 ) ) > 0xa0) { // 如果字符串中首个字节的ASCII序数值大于0xa0,则表示汉字 6 $tmpstr .= substr ( $str, $i, 3 ); // 每次取出三位字符赋给变量$tmpstr,即等于一个汉字 7 $i=$i+3; // 变量自加3 8 } else{ 9 $tmpstr .= substr ( $str, $i, 1 ); // 如果不是汉字,则每次取出一位字符赋给变量$tmpstr 10 $i++; 11 } 12 } 13 return $tmpstr; // 返回字符串 14 }
最后给上ecshop里面的截取UTF-8编码下字符串的函数:
1 define('EC_CHARSET','utf8'); 2 function sub_str($str, $length = 0, $append = true){ 3 $str = trim($str); 4 $strlength = strlen($str); 5 6 if ($length == 0 || $length >= $strlength){ 7 return $str; //截取长度等于0或大于等于本字符串的长度,返回字符串本身 8 }elseif ($length < 0){ //如果截取长度为负数 9 $length = $strlength + $length;//那么截取长度就等于字符串长度减去截取长度 10 if ($length < 0){ 11 $length = $strlength;//如果截取长度的绝对值大于字符串本身长度,则截取长度取字符串本身的长度 12 } 13 } 14 15 if (function_exists('mb_substr')){ 16 $newstr = mb_substr($str, 0, $length, EC_CHARSET); 17 }elseif (function_exists('iconv_substr')){ 18 //iconv_substr截取字符而不是字节数 19 $newstr = iconv_substr($str, 0, $length, EC_CHARSET); 20 }else{ 21 //$newstr = trim_right(substr($str, 0, $length)); 22 $newstr = substr($str, 0, $length); 23 } 24 25 if ($append && $str != $newstr){ 26 $newstr .= '...'; 27 } 28 29 return $newstr; 30 }
浙公网安备 33010602011771号