November 19,2008
Convert Multibytes String to UTF-8 using Python in Windows
很久沒寫文章,整個版冷清了不少XD。最近因緣際會之下開始接觸Python,搭配Django希望實作一個簡單功能:把Windows上的檔案列表呈現在網頁上,但因為對Python很不熟悉陷入很大的瓶頸:當檔案列表中有繁體中文字(Big5)與日文字(SHIFT_JIS)時,要轉成UTF-8並不是一件容易的事情。
(詳細描述如下↓)
我們先來複習一下,Python一開始對於Unicode的支援度不高(你一不小心在字串中輸入中文字網頁就炸掉了XD),好像在2.X之後的版本有了很大的改進,How to Use UTF-8 with Python ← 上面這篇文章提供了很好的轉碼與宣告方式。
Unicode()這個function提供了很好的橋梁讓多種編碼之間作互換,範例:把input string由Big5轉成utf-8編碼的result string (↓如下圖所示)
但是這邊出現個問題! 假使input_str中包含了日文字串,你這樣轉換會跳出錯誤,當然你也可以強制轉換,視而不見XDD (換來很多的????)
當然我們更希望能有更smart的方法去判斷到底輸入的string是什麼編碼?再來作轉碼,於是我又找到了一個framework:Universal Encoding Detector,這套framework提供一套algorithm去判斷輸入的字串所擁有編碼的比例,(支援的編碼語系),下面又作了一個簡單的demo
det = chardet.detect(input_str)
result_str = unicode(input_str, det['encoding']).encode('utf-8')
不過很可惜的事情又發生了,由於我的input_str都是檔名且都很短,了不起有50個字元就很不錯了,這樣判斷下去還真是五花八門,unicode()當然可預期得又跑出來抗議了。(可想而知這套algorithm是越多字元判斷的準確率越高)
很困惑,記得windows XP之後的檔案系統不是都支援unicode的嗎?明明在檔案列表看起來都很正常不會有亂碼發生,可是透過os.listdir()抓出來的檔名卻都是原本的編碼格式(有繁體中文, 簡體中文, 日文 ... 等)
終 於在強者我同學kudo的引進之下,才發現原來windows是有偷偷把檔名存成unicode,但它提供了兩套API,一套是會回傳編碼成 unicode的檔名,另一套會回傳原本的檔名編碼,而python很忠實的呈現了兩套API的回傳結果,由輸入的路徑編碼來決定,範例
result_str = ''
# 特別注意輸入的路徑為unicode, 結果才會為unicode
uni_f_names = os.listdir(u'C:\Python26')
for name in uni_f_names:
result_str += name.encode('utf-8')
更詳細的說明可以參考 All About Python and Unicode
打完收工Orz,就這樣一兩天就飛了^^!!!
technorati tags: python, multibyte, unicode, utf-8, encoding, 中文, 日文