php 中文截断,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

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

赞赏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值