utf-8 轉換至 big5

原本以為碰不到 big5 了說 XD hmm… 在 php 用 iconv 應該都要知道有 //translit 跟 //ignore 這兩個參數可以用, 使用 //translit 參數的話, 如果某個字無法順利轉換, 那麼根據 php manual 的說法是, iconv 會找相近的字代替, 如果真的不行就是用問號代替。 如果使用 //ignore 的話, 碰到沒辦法轉換的字, 就是直接略過那個字, 然後接續剩下的字串。 如果 //translit 跟 //ignore 這兩參數都沒有加, 那麼… 碰到沒辦法轉換的字, 那麼除了發生問題的字之外, 連後面後續的字串也都會不見, 就截斷了。 所以基本上這兩個參數應該是隨便選一個加都比不加好吧? 除非是 big5 轉 utf-8 等, 小字集轉大字集的狀況。

不過今天碰到某個問題, 碰到字串沒辦法轉換就得回覆使用者狀況, 所以寫了下面這一段來處理這個問題, 其中的 $utf8_str 包含了兩個無法轉換至 big5 的字元, “喆"跟"担"。

做法是利用 //translit 參數來轉換字串, 如果無法轉換就會變成問號, 那麼我們就可以從問號來知道字元的位置, 進而回覆使用者無法轉換的是哪些字, 而要求使用者修改, 使用替代的字。

另外, 由於是使用問號來處理, 所以得避開原本就存在的問號, 所以會先將 $utf8str 裡面的問號 replace 掉, 之後再還原回來即可。 下面混用了 iconv 跟 mbstring XD 應該可以把 mbstrlen 等函式換成 iconvstrlen 會比較統一 :p

$utf8_str = '陶喆, 要不要去吃担仔麵?';
$utf8_str = str_replace('?', '<strong>TEMP</strong>', $utf8_str);
$big5_str = iconv('utf8', 'big5//translit', $utf8_str);<p>$position = array();
$n = mb_strlen($big5_str, 'big5');
for ($i = 0; $i < $n; $i++) {  
    if (mb_substr($big5_str, $i, 1, 'big5') == '?') {
        $position[] = $i;
    }
}</p><p>if ($position) {
    $err_chars = '';
    foreach($position as $i) {
         $err_chars .= mb_substr($utf8_str, $i, 1, 'utf8') . ', ';
    }
    $err_chars = trim($err_chars, ', ');
    echo 'Sorry! ' . $err_chars . ' can not be converted';
} else {
    $utf8_str = str_replace('<strong>TEMP</strong>', '?', $utf8_str);
    echo $utf8_str;
}</p>```

然後下面這個其實沒啥關係, 是從網路上找來的, 可以用來檢查字元是否在 big5 字元集裡。 本來想用這個來作檢查, 問題是… 轉換後, 字元不是變問號就是不見了, 不過這個倒是可以用在 big5 的檢查, 而不是上面從 utf-8 轉換的情況。 只是試了一下, 真的是可以檢查, 不過好像逗點等會被視為 false, anyway, 雖然 big5 的處理在往後應該用不太到, 不過有興趣的人可以參考[大五碼](http://zh.wikipedia.org/wiki/大五碼)的 wiki 頁面, 裡面有位元組分區表格可以參考。

function big5_valid($str)
{ $bc = hexdec(bin2hex($str)); if (($bc >= 0xa440 AND $bc = 0xc940 AND $bc = 0xa140 AND $bc = 0xc6a1 AND $bc <= 0xc8fe) ) return true;

return false;

}```

tzangms

Read more posts by this author.

Subscribe to Oceanic / 海海人生

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!