亂碼 « beyond the void
1設計開發
555 views
最近在給opencc做圖形介面,遇到乙個問題:opencc預設只能轉換utf-8文字,其他編碼像gb18030,big5只能轉換成utf-8以後,才能用opencc轉換。這個問題說大不大,說小也不小。我完全可以增加乙個選項,在開啟的時候讓使用者選擇文字編碼,然後再轉換就行了,但這卻給使用者非常糟糕的體驗,因為很多非專業使用者根本不知道什麼是文字編碼,更別說辨別了。gb18030/big5硬要用utf-8開啟的話,肯定會遇到亂碼。由於windows預設是gb18030/big5編碼,一般情況下文字會被儲存成預設編碼,這樣更大大增加了使用者遇到亂碼的概率。為了提高體驗,我計畫實現文字編碼的自動檢測。
最早接觸到編碼是從做網站開始的,記得如果忘了在head中顯式地向瀏覽器指定編碼,就經常會出現亂碼,但亂碼也並不總是出現,這是怎麼回事呢?瀏覽器還是有自動識別的能力的。發現firefox瀏覽器中有乙個編碼選項,裡面有「自動檢測」,使用它絕大多數時候都能正確識別。
事實上純文字的編碼檢測是乙個非常複雜的問題,甚至理論上根本不可能實現。確切地說,「檢測」應該叫「探測」或者「推測」才更恰當。自動編碼探測的實現原理主要是統計學的方法,每個編碼會有一定的特徵,首先檢測特徵是否符合,再使用常用的匹配,類似於蒙特卡羅法。具體方法可以參考
mozilla在很多年前就做了乙個非常優秀的編碼檢測工具,叫chardet,後來有發布了演算法更加優秀的universalchardet,用於firefox的自動編碼識別。我想,這麼出名的乙個工具,應該肯定已經有不少人在用了。有意思的是,我在網上找到了chardet和universalchardet的各種移植:
惟一沒有的,竟然是c/c++的介面封裝。debian更是收錄了python-chardet和ruby-rchardet,卻沒有libchardet或者libuniversalchardet。莫非沒有c/c++的應用在使用chardet嗎?用強大的google程式碼搜尋,發現的確有,但幾乎都是把chardet的程式碼內嵌到了專案中,耦合十分緊密。更有直接呼叫python-chardet的,實現不夠純淨。
總覺不該是這樣,但經過反覆確認,真的沒有乙個獨立的universalchardet的c函式庫封裝。還是自己動手好了,我從mozilla上面取下來了程式碼,做了一點點補丁,寫了乙個介面和命令列介面,取名uchardet,大功告成。測試了一些gb18030和utf8的文字,感覺準確率非常高,而且速度很快。但是當我試圖識別幾個位元組的短文本的時候,卻出現了識別錯誤,開始以為是我的錯,後來發現我用firefox直接開啟,也是無法識別的,而且錯誤識別的編碼一樣。看來是上游的問題,應該是演算法本身的缺陷吧。想想看,畢竟文字越短歧義的可能性越強。不過既然能達到和firefox同樣的水平,一般應用也就夠了。
專案主頁在google code上:
程式碼在github上:
我為什麼用universalchardet?其實編碼自動識別的解決方案不止乙個,有icu提供的解決方案,ie也有api,還有已經在很多linux發行版中的enca。我之所以用universalchardet,是因為它是最合適的。ie的api不能跨平台,icu實現太龐大,enca是gpl(注意不是lgpl),使用它意味著我也要讓我的所有原始碼使用gpl,而不是更加開放的apache。universalchardet是mpl的,和lgpl差不多寬鬆,使用它是沒有問題的。我非常不喜歡以gpl發布的函式庫,這給開發者的限制太大了。
vim自動識別檔案編碼
1.檢視檔案編碼的方法 file filename 在vim中可以直接檢視檔案編碼方式 set fileencoding 即可顯示檔案編碼方式 2.設定vim使其自動識別檔案編碼 set encoding utf 8 fileencodings ucs bom,utf 8,cp936 這樣,就可以讓...
自動識別技術的分類
自動識別技術是應用一定的識別裝置,通過被識別物品和識別裝置之間的接近活動,自動地獲取被識別物品的相關資訊,並提供給後台的計算機處理系統來完成相關後續處理的一種技術。按照應用領域和具體特徵,自動識別技術可以分為 1.條碼識別技術 條碼是由一組條 空和數字符號組成,按一定編碼規則排列,用以表示一定的字元...
MSSqlServer新建查詢不自動識別新建表
mssqlserver新建查詢不自動識別新建表,需要重新開啟sql server資料庫才可以,自動提示新建表名,字段。在網上找到兩個解決方法 方法1 編輯 intellisense 重新整理本地快取 方法2 在sqlserver最後加上 go 伺服器有時是有滯後的,不給伺服器乙個明確的互動命令。sq...