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     }

 

  

posted on 2016-05-18 19:55  yycode  阅读(159)  评论(0)    收藏  举报

导航