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
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"!
赞赏