要知道怎么截取UTF8无乱码,我们首先要知道UTF8是怎么编码的,百度了一下,得出以下码表
Unicode/UCS-4
|
bit数
|
UTF-8
|
byte数
|
备注
|
0000 ~
007F
|
0~7
|
0XXX XXXX
|
1
| |
0080 ~
07FF
|
8~11
|
110X XXXX
|
2
| |
0800 ~
FFFF
|
12~16
|
1110XXXX
|
3
|
基本定义范围:0~FFFF
|
1 0000 ~
1F FFFF
|
17~21
|
1111 0XXX
|
4
|
Unicode6.1定义范围:0~10 FFFF
|
20 0000 ~
3FF FFFF
|
22~26
|
1111 10XX
|
5
|
说明:此非unicode编码范围,属于UCS-4 编码
早期的规范UTF-8可以到达6字节序列,可以覆盖到31位元(通用字符集原来的极限)。尽管如此,2003年11 月UTF-8 被 RFC3629 重新规范,只能使用原来Unicode定义的区域, U+0000到U+10FFFF。根据规范,这些字节值将无法出现在合法UTF-8序列中
|
400 0000 ~
7FFF FFFF
|
27~31
|
1111 110X
|
6
|
看起来很复杂,其实就很简单,utf8编码究竟是多少个字节组成一个字符,主要是看字符的第一个字节,至于第一个字节是什么样对应截取多少个就参照上表了,但是还有一个问题,就是究竟要怎么判断,其实只要截取第一个字节出来,位运算一次就可以了,具体代码如下
function getUTF8($str,$len){
if($len <= 0){
return '';
}
$temp = '';
for($i=0,$j=0;$i<$len;$i++){
$str1 = ord(substr($str,$j,1));
if(($str1 & bindec('11111110')) == bindec('11111100')){
//截取6
$temp .= substr($str,$j,6);
$j = $j + 6;
}elseif(($str1 & bindec('11111100')) == bindec('11111000')){
//截取5
$temp .= substr($str,$j,5);
$j = $j + 5;
}elseif(($str1 & bindec('11111000')) == bindec('11110000')){
//截取4
$temp .= substr($str,$j,4);
$j = $j + 4;
}elseif(($str1 & bindec('11110000')) == bindec('11100000')){
//截取3
$temp .= substr($str,$j,3);
$j = $j + 3;
}elseif(($str1 & bindec('11100000')) == bindec('11000000')){
//截取2
$temp .= substr($str,$j,2);
$j = $j + 2;
}else{
//截取1
$temp .= substr($str,$j,1);
$j = $j + 1;
}
}
return $temp;
}