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



***/



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章