utf8截取无乱码

时间:2023-01-10 14:59:24
要知道怎么截取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;
}