PHP utf8中文截取无乱码

/**
燕十八 公益PHP培训
课堂地址:YY频道88354001
学习社区:www.zixue.it
**/

<?php

/*
utf-8中文截取无乱码


思路:
如果你看到如下字节,
42 DC 34 af aa

想截取无乱码,那就说明,你知道
从42开始截几个字节,作为一个字符.

比如截1个,截取出来42

再从DC截,你得知道,从DC,往后是几个字节组成了一个字符.

...
...

类推,这样,截取出来的字节才能保证,正是是一个个的字符

所以,关键在于,如何判断一个utf-8字符的字节数?


答: 可以到wiki上查询utf-8的编码规范,那是最权威的.
查阅后得知

最高字节
0xxx xxxx ,1个字节
110xx xxxx , 2个字节
1110 xxxx, 3
1111 0xxxx 4...

*/

$str = '中华人aaaa民共b和国,万c岁';
/*
$str 是待截取的字符串
$len 是截取的字符数
*/

function utf8sub($str,$len) {
if($len <= 0) {
return '';
}

$length = strlen($str); //待截取的字符串字节数

// 先取字符串的第一个字节,substr是按字节来的
$offset = 0; // 这是截取高位字节时的偏移量
$chars = 0; // 这是截取到的字符数
$res = ''; // 这是截取的字符串

while($chars < $len && $offset < $length) { //只要还没有截取到$len的长度,就继续进行
$high = decbin(ord(substr($str,$offset,1))); // 重要突破,已经能够判断高位字节

if(strlen($high) < 8) {
// 截取1个字节
$count = 1;
} else if(substr($high,0,3) == '110') {
// 截取2个字节
$count = 2;

} else if(substr($high,0,4) == '1110') {
// 截取3个字节
$count = 3;

} else if(substr($high,0,5) == '11110') {
// 截取4个字节
$count = 4;

} else if(substr($high,0,6) == '111110') {
// 截取5个字节
$count = 5;

} else if(substr($high,0,7) == '1111110') {
// 截取6个字节
$count = 6;
}

// echo $count,'<br />';


$res .= substr($str,$offset,$count);
$chars += 1;
$offset += $count;

}

return $res;

}

echo utf8sub($str,200);
/***
我是用字符串来判断的,效率不高.

位运算效果会更好.

110x xxxx & 1110 0000 -> 1100 0000
1110 xxxx & 1111 0000 -> 1110 0000

***/

原文地址:https://www.cnblogs.com/qintangtao/p/2753564.html