• PHP中文字符串截断无乱码解决方案


    一个比较好用的字符串截取函数:

    function substring($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;  //return 28
    
    $len = strlen($str2);
    echo '<br />'.$len;  //return 29
    
    echo '<br />';    
    echo substring($str1, 0, 11);    
    echo '<br />';
    echo substring($str2, 0, 11);        
    echo '<br />';
    echo substring($str1, 16, 28);    
    echo '<br />';
    echo substring($str2, 16, 29);    

    结果显示:

    28
    29
    我是一串比较
    我是一串比较
    中文不带英文
    中文带yingwen

    这个函数十分有用,比如用来截断比较长的文件名,但是要在中间加上...,可以这样来做:

    function formatName($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;
        }
    }

    另外,网上看到一种超级简单的中文截断解决方案,试用了一下,效果也不错:

    echo substr($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单位长度,所以截断时需要注意长度设置。
    计算长度的方法:
    function strlen_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;
    } // End strlen_UTF8;

    字符串截断函数:

    function subString_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;
                    }
                }
            }
            return join($r);
        } // End subString_UTF8;

    使用方法和之前介绍的一样,比如formatName可以实现如下(这对汉字长度做了小优化):

    function formatName($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;
        }
    }
  • 相关阅读:
    [转]VS2010几款超赞的扩展辅助工具总结
    从客户端中检测到有潜在危险的Request.Form 值
    面试系列28 分布式服务接口的幂等性如何设计
    面试系列26 如何基于dubbo进行服务治理、服务降级、失败重试以及超时重试
    面试系列25 dubbo的spi思想是什么
    面试系列24 dubbo负载均衡策略和集群容错策略
    面试系列23
    面试系列22 dubbo的工作原理
    面试系列21 为什么要进行系统拆分
    面试系列20 生产环境中的redis是怎么部署的
  • 原文地址:https://www.cnblogs.com/jiji262/p/2574441.html
Copyright © 2020-2023  润新知