1. 程式人生 > >PHP擷取UTF8字串 utf-8 可以能佔一個字元 二個字元 或者三個字元

PHP擷取UTF8字串 utf-8 可以能佔一個字元 二個字元 或者三個字元

PHP擷取UTF8字串  

想必很多人從一開始接觸程式設計到現在,都有一個慣性思維:英文字元佔用一個位元組,中文字元佔用兩個位元組。不錯,英文字元是佔用一個位元組,但中文字元佔用兩個位元組是相對於GBK編碼而言(當然,其他一些編碼如GB2312也是),但是在時下國際流行的UTF8編碼中,一箇中文字元佔用3個位元組。不要驚訝,這是一個事實,而且應該成為一個常識。
UTF8編碼可能出現一個字元佔用1個、2個、3個甚至更多位元組的情況,如英文字元abc佔用一個位元組,中文字元佔用三個位元組,那麼什麼字元佔用兩個位元組呢?這個問題我一開始並沒有發現,只是前幾天有人留言,首頁的評論擷取竟然出現了亂碼的情況:

2011年09月21日 - bzyyc.happy - 點菸看寂寞燃燒
最開始並沒有發現這兩個亂碼出現的問題在哪裡,後來仔細驗證了下,發現是處在·這個字元上(鍵盤左上角,中文輸入法下),它佔用兩個位元組。而emlog的擷取字串函式,除了英文字元外,預設其他的都佔三個位元組了,因此導致亂碼出現。
查閱了相關資料,得出了一個結論:UTF8編碼的字元中,第一個位元組ASCII值大於等於224的,其與之後的2個位元組一起組成一個UTF8字元,第一個位元組ASCII值大於192等於小於224的,其與之後的1個位元組組成一個UTF-8字元,第一個位元組ASCII值小於192的,其本身成為一個UTF8字元。於是在PHP中將·字元的ASCII打印出來,第一個位元組是194,第二個位元組是183,木有第三個位元組了,於是擷取的字元中,若包含·字元,就會出現亂碼了。
問題找到,解決方案也就很簡單了,分別判斷處理下就OK。寫了如下函式用於擷取:


function subString($str, $start, $length) {     $i = 0;     //完整排除之前的UTF8字元     while($i < $start) {         $ord = ord($str{$i});         if($ord < 192) {             $i++;         } elseif($ord <224) {             $i += 2;         } else {             $i += 3;         }     }     //開始擷取     $result = '';     while($i < $start + $length && $i < strlen($str)) {         $ord = ord($str{$i});         if($ord < 192) {             $result .= $str{$i};             $i++;         } elseif($ord <224) {             $result .= $str{$i}.$str{$i+1};             $i += 2;         } else {             $result .= $str{$i}.$str{$i+1}.$str{$i+2};             $i += 3;         }     }     if($i < strlen($str)) {         $result .= '...';     }     return $result; }