用 php 把 unicode 轉成 UTF-8 的最簡方案
8 月 06
網路技術 UTF-8 No Comments / 8,311 views
越來越多資訊包含了多種語言,以往單純的 Big5 文件已經無法處理,所以大家漸漸傾向把文件輸出成 unicode 型式。然而,Unicode 不像 Big5 只是單純的雙位元字集,佔用固定的 code range 那樣單純,它的複雜度更高。
在尋找適合的 solutions 時,發現以 Java, C 此類語言的資源較為豐富,而 php 則是要到 php 6 之後才會內建,而且要編譯 International Components for Unicode 的相關模組。而現在大家慣用的 iconv 指令,卻無法在 unicode 的編碼方式作切換。(會的人麻煩 comment 指點一下喔,謝謝!)
花了一點時間爬文後,整理出以下的最簡方案:
Unicode 轉 UTF-8
首先,檢查檔案是否包含 Unicode BOM 標頭(\xFF\xFE)。
然後,兩兩取出字節,轉換成 binary string。
轉換過程中,利用 $cache 雜湊表來節省不必要的運算;而 ASCII 區段的文字則另外經過 iconv 的轉換以相容部份特殊符號。(以下字碼轉換的程式參考自 CentralNic Unicode Library,但修正了原碼中對 $dec < 128 的設定,將之擴大為 256 以改善其特殊符號不相容的問題。)
程式碼如下:
function unicode_to_utf8($text='') { $cache = array() ; $text = preg_replace("/^\\xFF\\xFE/","",$text) ; for ($i = 0 ; $i < strlen($text) ;) { $dec = ord(substr($text,$i + 1,1)) * 256 + ord(substr($text,$i,1)) ; $i += 2 ; if (!array_key_exists($dec,$cache)) { if ($dec < 256) $cache[$dec] = iconv('ISO-8859-1','UTF-8',chr($dec)) ; else if ($dec < 2048) $cache[$dec] = chr(192 + (($dec - ($dec % 64)) / 64)) . chr(128 + ($dec % 64)) ; else $cache[$dec] = chr(224 + (($dec - ($dec % 4096)) / 4096)) . chr(128 + ((($dec % 4096) - ($dec % 64)) / 64)) . chr(128 + ($dec % 64)) ; } $string .= $cache[$dec] ; } return $string ; }用 php 把 unicode 轉成 UTF-8 的最簡方案,