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 (↓如下圖所示)

result_str = unicode(input_str, 'Big5').encode('utf-8')

 

但是這邊出現個問題! 假使input_str中包含了日文字串,你這樣轉換會跳出錯誤,當然你也可以強制轉換,視而不見XDD (換來很多的????)

result_str = unicode(input_str, 'Big5', 'ignore').encode('utf-8')

 

當然我們更希望能有更smart的方法去判斷到底輸入的string是什麼編碼?再來作轉碼,於是我又找到了一個framework:Universal Encoding Detector,這套framework提供一套algorithm去判斷輸入的字串所擁有編碼的比例,(支援的編碼語系),下面又作了一個簡單的demo

import chardet
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的回傳結果,由輸入的路徑編碼來決定,範例

import os
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,就這樣一兩天就飛了^^!!!

Technoratitechnorati tags: , , , , , ,


Posted by evilsmile at 樂多Roodo! │23:50 │回應(0)引用(0)Programming_程式語言
樂多分類:網路/3C 工具:編輯本文
Ads by Roodo! 

引用URL

http://cgi.blog.roodo.com/trackback/7637773