utf8中文截断原理以及php的实现

php截断字符串用的是substr,但是这个是无法截断中文的,原因就是中文是采用多字节编码。这里说一下针对utf8编码的汉字截断原理。

UTF-8的编码规则是这样的

1)对于单字节的符号,字节的第一位(字节的最高位)设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。

2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

下表总结了编码规则,字母x表示可用编码的位。

UTF-8编码方式(十六进制) | 十进制|(二进制)
—————+———————————————————————
0000 0000-0000 007F |0 – 127      | 0xxxxxxx
0000 0080-0000 07FF |192 – 223  |110xxxxx 10xxxxxx
0000 0800-0000 FFFF |224 – 239  |1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF |240 – 247  |11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

更详细的可以去看看utf8编码原理

知道了编码规则,那也就可以针对utf8编码来写出截断函数了。

要用到的函数有

strlen()计算字符串长度

substr()单字节截断字符串

ord()获取字符的ascii码

我们要做的就是遍历字符串的字节数,根据ascii的值有针对性的截断,最后再拼出一个截断后的字符串

首先看看下面代码输出了什么

$str = "你好";
    $len = strlen($str);//计算字符串长度
    $i = 0;
    while( $i<$len ){
        echo $ascii = ord($str[$i]);//计算ascii值
        echo "\n";
    $i++;
}

结果是

228
189
160
229
165
189

可以看到,你好这两个字每一个字都是由多个字节构成的,至于是两个,三个,四个我们却不知道了,不过只要知道,这个文字的第一个ascii的范围,我们就知道这个汉字是由多少字节组成了。

你好,你字的第一位是228,可以看到是在第三个区间,因此你是三个字节编码,228 189 160 表示“你”,下面是229,同样在第三个区间,229 165 189表示“好”。

根据编码规则,我们很容易就能够写出字符串截断函数了

找到这个汉字的字节长度,然后截取对应的长度,整个汉字就被截取下来了,接着找下一个,就这样,一个utf8字符串截取的函数就完成了

下面写了一个

/**
  * utf8_substr 一个简单地中文截断函数
  *
  * @param  string $str    等待截断的utf8字符串
  * @param  int $start  起始位置
  * @param  int $sublen 截断长度
  * @return str         新的字符串
  */
 function utf8_substr($str,$start,$sublen){
     $len = strlen($str);
     $i = 0;
     $newstr = '';
     $strpos = 1;
     while( $i < $len ){
        $ascii = ord($str[$i]);
        $end = 1;

        if( $ascii >= 192 && $ascii <= 223 ){
            $end = 2;
        }
        if( $ascii >=224 && $ascii <=239 ){
            $end = 3;
        }
        if( $ascii >=240 && $ascii <= 247 ){
            $end = 4;
        }

        //从大于起始长度开始截取
        if( $strpos > $start ){
            $newstr .= substr($str, $i, $end);
        }

        $i += $end;
        $strpos += 1;

        //超出长度则跳出
       if( ($strpos-$start) > $sublen) break;

    }

    echo $newstr;

}

//用法
utf8_substr("你asdas",0,3);

//这个将会输出"你as"!

赞赏

微信赞赏支付宝赞赏

发表评论

电子邮件地址不会被公开。 必填项已用*标注