1. 程式人生 > >(轉)Unicode和Python的中文處理

(轉)Unicode和Python的中文處理

      ——由於最近在做有關網頁搜尋的專案,涉及到一些編碼方面的知識,小弟在網上偶然地發現了這麼一篇文章,很易懂,不晦澀,為了方便自己也同時能方便大家,就轉了過來,以作參考……

Unicode和Python的中文處理
  在Python語言中,Uincode字串處理一直是一個容易讓人迷惑的問題。許多Python
愛好者經常因為搞不清Unicode、UTF-8還有其它許許多多的編碼之間的區別而大傷腦筋。
筆者曾經也是這“傷腦筋一族”的成員,但經過半年多的努力,現在終於初步弄清楚其中
的一些關係。現將其整理如下,與各位同仁同享。同時也希望能借這篇短文拋磚引玉,吸
引更多真正的高手加入進來,共同完善我們的Python中文環境。

  本文所提到的各種觀點,一部分是查閱資料所得,還有一部分是筆者利用已有各種編
碼資料用“猜測加驗證”法得到。筆者自問才疏學淺,其中怕是藏有不少錯誤。各位看官
中不乏高手,如果有哪一位發現其中哪裡有錯,萬望各位高人不吝賜教。筆者自己丟醜事
小,觀點錯誤誤了別人事大,因此各位大可不必顧忌筆者的面子問題。


第一節 文字編碼和Unicode標準

  要解釋Unicode字串就必須先從什麼是Unicode編碼開始說起。眾所周知,文字顯示
一直是計算機顯示功能必須解決的基本問題。而計算機並不識字,它實際上是把文字看做
是一串“圖片”,每張“圖片”對應一個字元。每個計算機程式在顯示文字時,必須藉助
一個記錄這個文字“圖片”如何顯示的“圖片”集合,從中找到每一個字元對應“圖片”
的資料,並依樣畫葫蘆地把這個字“畫”到螢幕上。這個“圖片”就被稱為“字模”,而
記錄字模顯示資料的集合就被稱為“字符集”。為方便程式查詢,每個字元的字模資料在
字符集中必須是有序排列的,而且每個字元都會被分配一個獨一無二的ID,這個ID就是字
符的編碼。而在計算機進行字元資料處理時,總是用這個編碼代表它表示的那個字元。因
此,一個字符集就規定了一組計算機能夠處理的字元資料。顯然,不同國家指定的字符集
大小不同,相應的字元編碼也不同。

  在計算機歷史上,最為廣泛使用的標準化字符集當首推ASCII字符集。它實際上是美
國制訂的標準,針對北美使用者開發。它使用7個二進位制位編碼,可以表示128個字元。這個
字符集最終被ISO組織正式採納為國際標準,並且大量應用在各種計算機體系上。現如今,
所有PC機的BIOS中都內含了ASCII字符集的字模,其深入人心可見一斑。

  但是,當計算機在各個國家大規模普及時,ASCII編碼的侷限性就暴露出來了:它的
字元空間實在有限,無法容納更多的字元,可是絕大多數語言需要使用的字元數目都遠不
止128個。為了能正確處理本國文字,各個國家官方或民間紛紛開始了設計本國文字編碼
集的工作,並且最終湧現出許許多多針對各個國家文字的字元編碼,如針對西歐字元的
ISO-8859-1編碼,針對簡體中文的GB系列編碼,還有針對日文的SHIFT-JIS編碼等等。同
時,為了保證各個新的字符集能夠相容原本的ASCII文字,大多數字符集不約而同地都將
ASCII字元作為自己前128個字元,並使其編碼與ASCII編碼一一對應。

  這樣一來,各國文字的顯示問題是解決了,可是又帶來一個新的問題:亂碼。不同國
家、地區使用的字符集通常沒有統一的規範進行約束,因此各個字符集編碼往往互不兼
容。同一個字在兩個不同的字符集中編碼一般不同;而同一個編碼在不同的字符集中對應
的字元也不一樣。一段用編碼A編寫的文字在一個只支援編碼B的系統上往往會被顯示成一
堆亂七八糟的字元。更糟糕的是,不同字符集使用的編碼長度往往也不相同,那些只能處
理單位元組編碼的程式在遇到雙位元組甚至是多位元組編碼的文字時,往往因為不能正確處理而
產生了臭名昭著的“半個字”問題。這使得本已經混亂不堪的局面更是亂成了一團粥。

  為了一勞永逸地解決這些問題,業界許多大公司和組織聯合提出了一個標準,這就是
Unicode。Unicode實際上是一種新的字元編碼體系。它對字符集中的每個字元用兩個位元組
長的ID號進行編碼,從而規定出一個可容納多達65536個字元的編碼空間,並且將現今國
際上各國編碼中的常用字盡數收入罄中。由於在設計編碼時有了周全的考慮,Unicode很
好地解決了其它字符集在進行資料交流時的亂碼和“半個字”問題。同時,Unicode的設
計者充分考慮到現今大量字模資料使用的仍是各國制訂的各種編碼這一現實,提出了“將
Unicode作為內部編碼”的設計理念。也就是說,字元顯示程式依然使用原先的編碼和代
碼,而應用程式的內部邏輯使用的將是Unicode。當要進行文字顯示時,程式總是將
Unicode編碼的字串轉換成原本的編碼進行顯示。這樣,大家就不必為了使用Unicode而
重新設計字模資料體系了。同時,為了與各國已經制訂的編碼相區別,Unicode的設計者
將Unicode稱為“寬字元編碼”(wide characters encodings),而各國制訂的編碼習慣
上被稱為“多位元組編碼”(multi bypes encodings)。時至今日,Unicode體系又引入了
四位元組的擴充套件編碼,並且逐漸與與UCS-4,也就是ISO10646編碼規範合流,希望有朝一日
能夠用ISO10646體系統一全世界所有的文字編碼。

  Unicode體系甫一出世便被大家寄予厚望,並被迅速接受為ISO認可的國際標準。但
是,Unicode在推廣過程中卻遭到了首先是歐美使用者的反對。他們反對的理由非常簡單:
歐美使用者原本使用的編碼都是單位元組長的,雙位元組的Unicode處理引擎無法處理原本的單
位元組資料;而如果要把現有的單位元組文字全部轉換成Unicode,工作量就太大了。再說,
如果所有的單位元組編碼文字都被轉換成雙位元組的Unicode編碼,他們所有的文字資料佔用
的空間都會變成原來的兩倍,而且所有的處理程式都要被重新編寫。這個開銷他們無法接
受。

  雖然Unicode是國際認可的標準,但是標準化組織不可能不考慮歐美使用者這個最大的
計算機使用群體的要求。於是在各方磋商之下,一個Unicode的變種版本產生了,這就是
UTF-8。UTF-8是一個多位元組的編碼體系,它的編碼規則如下:

  1、UTF-8編碼分為四個區:
    一區為單位元組編碼,
      編碼格式為:0xxxxxxx;
      對應Unicode:0x0000 - 0x007f
    二區為雙位元組編碼,
      編碼格式為:110xxxxx 10xxxxxx;
      對應Unicode:0x0080 - 0x07ff
    三區為三位元組編碼,
      編碼格式為:1110xxxx 10xxxxxxx 10xxxxxx
      對應Unicode:0x0800 - 0xffff
    四區為四位元組編碼,
      編碼格式為:11110xxx 10xxxxxxx 10xxxxxx 10xxxxxx
      對應Unicode:0x00010000 - 0x0001ffff
    五區為五位元組編碼,
      編碼格式為:111110xx 10xxxxxxx 10xxxxxxx 10xxxxxxx 10xxxxxxx
      對應Unicode:0x00200000 - 0x03ffffff
    六區為六位元組編碼,
      編碼格式為:111110x 10xxxxxxx 10xxxxxxx 10xxxxxxx 10xxxxxxx 10xxxxxxx
      對應Unicode:0x04000000 - 0x7fffffff

   其中,一、二、三區對應Unicode的雙位元組編碼區,而四區則針對Unicode的四位元組
擴充套件部分(按照該定義,UTF-8還有五區和六區,但筆者並未在GNU glibc庫中發現,不知
為何);

  2、各個區按照一、二、三、四、五、六順序排列,其對應位置上的字元與Unicode保
持相同;

  3、不可顯示的Unicode字元編碼為0位元組,換言之,它們沒有被收入UTF-8(這是筆者
從GNU C庫註釋中得到的說法,可能與實際情況不符);

  按照UTF-8編碼規則我們不難發現,其一區的128個編碼實際上就是ASCII編碼。所以
UTF-8的處理引擎可以直接處理ASCII文字。但是,UTF-8對ASCII編碼的相容是以犧牲其它
編碼為代價的。比如,原本中、日、韓三國文字基本上都是雙位元組編碼,但它們在
Unicode編碼中的位置對應到UTF-8中的三區,每一個字元編碼要三個位元組長。換句話說,
如果我們把所有現有的中、日、韓三國編碼的非ASCII字元文字資料轉換成UTF-8編碼,則
其大小都會變成原來的1.5倍。

  雖然筆者個人認為UTF-8的編碼方式顯得有些不夠公平,但它畢竟解決了ASCII文字到
Unicode世界的過渡問題,所以還是贏得了廣泛的認可。典型的例子是XML和Java:XML文
本的預設編碼就是UTF-8,而Java原始碼實際上就可以用UTF-8字元編寫(JBuilder的使用者
應該有印象)。另外還有開源軟體世界中大名鼎鼎的GTK 2.0,它使用UTF-8字元作為內部
編碼。

  說了這麼多,似乎話題有些扯遠了,許多Python愛好者可能已經開始著急:“這和
Python有什麼關係呢?”好的,現在我們就把視線轉到Python的世界來。


第二節 Python的Unicode編碼系統

  為了正確處理多語言文字,Python在2.0版後引入了Unicode字串。從那時起,
Python語言中的字串就分為兩種:一種是2.0版之前就已經使用很久的傳統Python字元
串,一種則是新的Unicode字串。在Python語言中,我們使用unicode()內建函式對一個
傳統Python字串進行“解碼”,得到一個Unicode字串,然後又通過Unicode字串的
encode()方法對這個Unicode字串進行“編碼”,將其“編碼”成為傳統Python字串
以上內容想必每一個Python使用者都是爛熟於胸了。但是你可知道,Python的Unicode字元
串並不是真正意義上的“Unicode編碼的字串”,而是遵循一種自己特有的規則。這個
規則的內容簡單得很:

  1、ASCII字元的Python Unicode編碼與它們的ASCII編碼相同。也就是說,Python的
Unicode字串中ASCII文字仍然是單位元組長度編碼;

  2、ASCII字元以外的字元,其編碼就是Unicode標準編碼的雙位元組(或四位元組)編碼。

  (筆者猜想,之所以Python社群要制訂如此古怪的標準,可能是想保證ASCII字串
的通用性吧)

  通常在Python應用中,Unicode字串都是作為內部處理時使用,而終端顯示工作則
由傳統的Python字串完成(實際上,Python的print語句根本無法打印出雙位元組的
Unicode編碼字元)。在Python語言中,傳統Python字串就是所謂的“多位元組編碼”字
符串,用於表示各種被“編碼”成為具體字符集編碼的字串(比如GB、BIG5、KOI8-R、
JIS、ISO-8859-1,當然也有UTF-8);而Python Unicode字串則是“寬字元編碼”字
符串,表示從具體字符集編碼中“解碼”出來的Unicode資料。所以通常情況下,一個需
要用到Unicode編碼的Python應用往往會以如下方式處理字串資料:

def foo(string, encoding = "gb2312"):
# 1. convert multi-byte string to wide character string
u_string = unicode(string, encoding)

# 2. do something
...

# 3. convert wide character string to printable multi-byte string
return u_string.encode(encoding)

  我們可以舉出一個例子:經常在Red Hat Linux環境中使用PyGTK2進行XWindow程式設計的
Python同道可能早就發現過這樣的情況:如果我們直接寫出如下語句:

import pygtk
pygtk.require('2.0')
import gtk

main = gtk.Window() # create a window
main.set_title("你好") # NOTICE!

  這樣的語句在執行時會在終端上出現這樣的警告:

Error converting from UTF-8 to 'GB18030': 轉換輸入中出現無效字元序列

並且程式視窗標題不會被置為“你好”;但如果使用者安裝了中文的codec,並將上文的最
後一句改為:

u_string = unicode('你好','gb2312')
main.set_title(u_string)

則程式視窗標題將會被正確地設定為“你好”。這是為什麼呢?

  原因很簡單。gtk.Window.set_title()方法總是將自己接收的標題字串看做是一個
Unicode字串。PyGTK系統在接收到使用者的main.set_title()這一請求時,將得到的字元
串在某處做了如下處理:

class Window(gtk.Widget):
...
def set_title(self, title_unicode_string):
...
# NOTICE! unicode -> multi-byte utf-8
real_title_string = title_unicode_string.encode('utf-8')
...
# pass read_title_string to GTK2 C API to draw the title
...

  我們看到,字串title_unicode_string在程式內部被“編碼”成了一個新的字元
串:real_title_string。顯然,這個real_title_string是一個傳統Python字串,而它
的編碼用的是UTF-8。在上一節中筆者曾經提到過,GTK2的內部使用的字串都是按UTF-8
編碼的,所以,GTK2核心系統在接收到real_title_string後可以正確顯示出標題來。

  那麼,如果使用者輸入的標題是ASCII字串(比如:“hello world”),又當如何?
我們回想一下Python Unicode字串的定義規則就不難發現,如果使用者的輸入是ASCII字
符串,則對其進行重編碼得到的就是其自身。也就是說,如果title_unicode_string的值
是ASCII字串,則real_title_string與title_unicode_string的值將完全一致。而一個
ASCII字串也就是一個UTF-8字串,把它傳遞給GTK2系統不會有任何問題。

  以上我們舉的例子是關於Linux下的PyGTK2的,但類似的問題不僅出現在PyGTK中。除
了PyGTK之外,現今各種Python繫結的圖形包,如PyQT、Tkinter等,多多少少都會遇到與
Unicode處理有關的問題。

  現在我們弄清了Python的Unicode字串編碼機制,但是我們最想知道的問題還是沒
有解決:我們如何才能讓Python支援用Unicode處理中文呢?這個問題我們將在下一節說
明。


第三節 如何讓Python的Unicode字串支援中文

  看完這一節的標題,有一些Python同道們可能會有些不以為然:“為什麼一定要用
Unicode處理中文呢?我們平時用傳統Python字串處理得不是也不錯嗎?”的確,其實
在一般情況下像字串連線、子串匹配等操作用傳統Python字串也就足夠了。但是,如
果涉及到一些高階的字串操作,比如包含多國文字的正則表示式匹配、文字編輯、表達
式分析等等,這些大量混雜了單位元組和多位元組文字的操作如果用傳統字串處理就非常麻
煩了。再說,傳統字串始終無法解決那該死的“半個字”問題。而如果我們可以使用
Unicode,則這些問題都可以迎刃而解。所以,我們必須正視並設法解決中文Unicode的處
理問題。

  由上一節的介紹我們知道,如果要想利用Python的Unicode機制處理字串,只要能
夠擁有一個能夠把多位元組的中文編碼(包括GB編碼系列和BIG5系列)和Unicode編碼進行
雙向轉換的編碼/解碼模組就可以了。按照Python的術語,這樣的編碼/解碼模組被稱為
codec。於是接下來的問題就變成了:我們該如何編寫這樣一個codec?

  如果Python的Unicode機制是硬編碼在Python核心中的話,那麼給Python新增一個新
的codec就將是一項艱苦卓絕的工作了。幸虧Python的設計者們沒有那麼傻,他們提供了
一個擴充性極佳的機制,可以非常方便地為Python新增新的codecs。

  Python的Unicode處理模組有三個最重要的組成部分:一是codecs.py檔案,二是
encodings目錄,三是aliases.py檔案。前兩者都位於Python系統庫的安裝目錄之中(如
果是Win32發行版,就在$PYTHON_HOME/lib/目錄下;如果是Red Hat Linux,就在
/usr/lib/python-version/目錄下,其它系統可以照此尋找),而最後一個則位於
encodings目錄下。接下來,我們分別對這三者加以說明。

  先來看看codecs.py檔案。這個檔案定義了一個標準的Codec模組應有的介面。其具體
內容大家可以在自己的Python發行版中找到,在此不再贅述。按照codecs.py檔案的定義,
一個完整的codec應該至少擁有三個類和一個標準函式:

  1、Codec類

  用途:
    用於將使用者傳入的緩衝區資料(一個buffer)作為一個傳統Python字串,並將
其“解碼”為對應的Unicode字串。一個完整的Codec類定義必須提供Codec.decode()和
Codec.encode()兩個方法:


  Codec.decode(input, errors = "strict")

  用於將輸入的資料看做是傳統Python字串,並將其“解碼”,轉換成對應的Unicode
字串。

  引數:

  input:輸入的buffer(可以是字串,也可以是任何可以轉換成字串表示的物件)
  errors:發生轉換錯誤時的處理選擇。可選擇如下三種取值:
    strict(預設值):如果發生錯誤,則丟擲UnicodeError異常;
    replace:如果發生錯誤,則選取一個預設的Unicode編碼代替之;
    ignore:如果發生錯誤,則忽略這個字元,並繼續分析餘下的字元。

  返回值:
    一個常數列表(tuple):首元素為轉換後的Unicode字串,尾元素為輸入資料
的長度。


  Codec.encode(input, errors = "strict")

  用於將輸入的資料看做是Unicode字串,並將其“編碼”,轉換成對應的傳統
Python字串。

  引數:

  input:輸入的buffer(通常就是Unicode字串)
  errors:發生轉換錯誤時的處理選擇。取值規則與Codec.decode()方法相同。

  返回值:
    一個常數列表(tuple):首元素為轉換後的傳統Python字串,尾元素為輸入
資料的長度。

  2、StreamReader類(通常應該繼承自Codec類)

  用於分析檔案輸入流。提供所有對檔案物件的讀取操作,如readline()方法等。

  3、StreamWriter類(通常應該繼承自Codec類)

  用於分析檔案輸出流。提供所有對檔案物件的寫入操作,如writeline()方法等。

  5、getregentry()函式

  即“GET REGistry ENTRY”之意,用於獲取各個Codec檔案中定義的四個關鍵函式。
其函式體統一為:

def getregentry():
return tuple(Codec().encode,Codec().decode,StreamReader,StreamWriter)

  在以上提到的所有四個類中,實際上只有Codec類和getregentry()函式是必須提供
的。必須提供前者是因為它是實際提供轉換操作的模組;而後者則是Python系統獲得
Codec定義的標準介面,所以必須存在。至於StreamReader和StreamWriter,理論上應該
可以通過繼承codecs.py中的StreamReader和StreamWriter類,並使用它們的預設實現。
當然,也有許多codec中將這兩個類進行了改寫,以實現一些特殊的定製功能。


  接下來我們再說說encodings目錄。顧名思義,encodings目錄就是Python系統預設的
存放所有已經安裝的codec的地方。我們可以在這裡找到所有Python發行版自帶的
codecs。習慣上,每一個新的codec都會將自己安裝在這裡。需要注意的是,Python系統
其實並不要求所有的codec都必須安裝於此。使用者可以將新的codec放在任何自己喜歡的位
置,只要Python系統的搜尋路徑可以找得到就行。


  僅僅將自己寫的codec安裝在Python能夠找到的路徑中還不夠。要想讓Python系統能找
到對應的codec,還必須在Python中對其進行註冊。要想註冊一個新的codec,就必須用到
encodings目錄下的aliases.py檔案。這個檔案中只定義了一個雜湊表aliases,它的每個
鍵對應著每一個codec在使用時的名稱,也就是unicode()內建函式的第二個引數值;而每
個鍵對應的值則是一個字串,它是這個codec對應的那個處理檔案的模組名。比如,
Python預設的解析UTF-8的codec是utf_8.py,它存放在encodings子目錄下,則aliases哈
希表中就有一項表示其對應關係:

'utf-8' : 'utf_8', # the module `utf_8' is the codec for UTF-8

同理,如果我們新寫了一個解析‘mycharset’字符集的codec,假設其編碼檔案為
mycodec.py,存放在$PYTHON_HOME/lib/site-packages/mycharset/目錄下,則我們就必
須在aliases雜湊表中加入這麼一行:

'mycharset' : 'mycharset.mycodec',

這裡不必寫出mycodec.py的全路徑名,因為site-packages目錄通常都在Python系統的搜
索路徑之中。

  Python直譯器在需要分析Unicode字串時,會自動載入encodings目錄下的這個
aliases.py檔案。如果mycharset已經在系統中註冊過,則我們就可以像使用其它內建的
編碼那樣使用我們自己定義的codec了。比如,如果按照上面的方式註冊了mycodec.py,
則我們就可以這樣寫:

my_unicode_string = unicode(a_multi_byte_string, 'mycharset')

print my_unicode_string.encode('mycharset')


  現在我們可以總結一下要編寫一個新的codec一共需要那些步驟:

  首先,我們需要編寫一個自己的codec編碼/解碼模組;

  其次,我們要把這個模組檔案放在一個Python直譯器可以找到的地方;

  最後,我們要在encodings/aliases.py檔案中對其進行註冊。


  從理論上說,有了這三步,我們就可以將自己的codec安裝到系統中去了。不過這樣
還不算完,還有一個小問題。有時候,我們出於種種原因,不希望隨便修改自己的系統文
件(比如,一個使用者工作在一個集中式的系統中,系統管理員不允許別人對系統檔案進行
修改)。在以上介紹的步驟中,我們需要修改aliases.py檔案的內容,這是一個系統文
件。可如果我們不能修改它,難道我們就不能新增新的codec嗎?不,我們當然有辦法。

  這個辦法就是:在執行時修改encodings.aliases.aliases雜湊表的內容。

  還是使用上面那個假設,如果使用者工作系統的管理員不允許使用者把mycodec.py的註冊
資訊寫入aliases.py,那麼我們就可以如此處理:

  1、將mycodec.py放在一個目錄下,比如/home/myname/mycharset/目錄;

  2、這樣編寫/home/myname/mycharset/__init__.py檔案:

import encodings.aliases

# update aliases hash map
encodings.aliases.aliases.update({/
'mycodec' : 'mycharset.mycodec',/
}}

  以後每次要使用Python時,我們可以將/home/myname/加入搜尋路徑,並且在使用自己
的codec時預先執行:

import mycharset # execute the script in mycharset/__init__.py

  這樣我們就可以在不改動原有系統檔案的情況下使用新的codecs了。另外,如果藉助
Python的site機制,我們還可以讓這個import工作自動化。如果大家不知道什麼是site,
就請在自己的Python互動環境中執行:

import site
print site.__doc__

瀏覽一下site模組的文件,即可明白箇中技巧。如果大家手頭有Red Hat Linux v8,v9,
還可以參考一下Red Hat的Python發行版中附帶的日文codec,看看它是如何實現自動載入
的。也許不少同道可能找不到這個日文的codec在哪裡,這裡列出如下:

  Red Hat Linux v8:在/usr/lib/python2.2/site-package/japanese/目錄下;
  Red Hat Linux v9:在/usr/lib/python2.2/lib-dynload/japanese/目錄下;

提示:請Red Hat使用者注意site-packages目錄下的japanese.pth檔案,結合site模組的文
檔,相信馬上就能豁然開朗。


結束語

  記得當初筆者在Dohao論壇上誇下海口:“如果可以的話,我可以為大家編寫一個
(中文模組)”,現在回想起來,不禁為自己當初的不知天高地厚而汗顏。一個把自己所
有的的時間都花在學習上,一個學期只學七門課程,還落得個兩門課不及格的傻瓜研究
生,哪裡有什麼資格在大家面前如此囂張。現如今,第二個學期由於這兩門課的緣故負擔
陡增(十門課呀!),家中老父老母還眼巴巴地等著自己的兒子能給他們掙臉。要想在有
限的時間之內,既保證學習,又保證工作(我要承擔導師的課程輔導工作,同時還有一
個學校的教學改革方案需要我在其中挑大樑),已經是疲於應付,再加上一個中文模
塊……唉,請恕筆者分身乏術,不得不食言。

  因此,筆者斗膽,在此和盤托出自己這半年以來的心得,只希望能夠找到一批,不,
哪怕是一個也好,只要是對這個專案感興趣的同道中人,能夠接下筆者已經整理出來的知
識,把一個完整的(至少應該包含GB、BIG5、筆者個人認為甚至還應包括HZ碼)中文模組
編寫出來,貢獻給大家(不論是有償的還是無償的),那就是我們廣大Python愛好者之福
了。另外,Python的發行版至今尚未包括任何中文支援模組。既然我等平日深愛Python,
如果我們的工作能因此為Python的發展做出一點貢獻,何樂而不為呢?


附錄 幾個小小提示

  1、LUO Jian兄已經編寫了一個非常不錯的中文模組(Dohao上有連結,檔名是
showfile.zip,這個模組比我已經寫完的草稿版本要快得多),同時支援GB2312和
GB18030編碼,可惜不支援BIG5。如果大家有興趣,可以下載這個模組研究一下;

  2、和其它字符集編碼相比,中文模組有其特殊性,那就是其海量的字元數目。一些
相對較小的字符集還好說,比如GB2312,可以利用雜湊表查詢。而對於巨大的GB18030編
碼,如果簡單地將所有資料製成一個特大的編碼對照表,則查詢速度會慢得讓人無法容忍
(筆者在編寫模組時最頭疼的就是這一點)。如果要編寫一個速度上能讓人滿意的codec,
就必須考慮設計某種公式,能夠通過簡單地運算從一種編碼推算出另一種來,或者至少能
推算出它的大概範圍。這就要求程式設計師要能對整個編碼方案做統計,設法找到規律。筆者
認為,這應該是編寫中文模組時的最大難點。或許是數學功底實在太差的緣故,筆者費盡
心機也未能找出一個規律來。希望能有數學高手不吝賜教;

  3、中文編碼分為兩大派系:GB和BIG5。其中GB又分為GB2312、GBK和、GB18030三種
編碼,而BIG5也分為BIG5和BIG5-HKSCS兩種(分別對應原始的BIG5和香港擴充套件版本)。雖
然同一派系的編碼可以向下相容,但考慮到其字元數目龐大,為了加快查詢速度,筆者個
人認為還是將它們分開編碼比較合理。當然,如果能夠找到對應字符集的轉換公式,則這
種分離就沒有必要了

相關推薦

UnicodePython中文處理

      ——由於最近在做有關網頁搜尋的專案,涉及到一些編碼方面的知識,小弟在網上偶然地發現了這麼一篇文章,很易懂,不晦澀,為了方便自己也同時能方便大家,就轉了過來,以作參考…… Unicode和Python的中文處理  在Python語言中,Uincode字串處理一直

十道海量資料處理面試題與十個方法大總結

      首先是這一天,並且是訪問百度的日誌中的IP取出來,逐個寫入到一個大檔案中。注意到IP是32位的,最多有個232個IP。同樣可以採用對映的方法,比如模1000,把整個大檔案對映為1000個小檔案,再找出每個小文中出現頻率最大的IP(可以採用hash_m

計算機視覺與影象處理、模式識別、機器學習學科之間的關係

在我的理解裡,要實現計算機視覺必須有影象處理的幫助,而影象處理倚仗於模式識別的有效運用,而模式識別是人工智慧領域的一個重要分支,人工智慧與機器學習密不可分。縱觀一切關係,發現計算機視覺的應用服務於機器學習。各個環節缺一不可,相輔相成。 邏輯線路:計算機視覺→影象處理→模式識

深入理解HTTP協議 瀏覽器伺服器如何通訊(HTTP協議)

          http協議學習系列 1. 基礎概念篇 1.1 介紹   HTTP是Hyper Text Transfer Protocol(超文字傳輸協議)的縮寫。它的發展是全球資訊網協會(World Wide Web Consortium)和Internet工作小組IETF(Internet En

深入理解HTTP協議 瀏覽器伺服器如何通訊(HTTP協議)

          http協議學習系列 1. 基礎概念篇 1.1 介紹   HTTP是Hyper Text Transfer Protocol(超文字傳輸協議)的縮寫。它的發展是全球資訊網協會(World Wide Web Consortium)和Internet工作小組

maven POM的中文參考手冊

外掛管理     pluginManagement:外掛管理以同樣的方式包括外掛元素,用於在特定的專案中配置。所有繼承於此專案的子專案都能使用。主要定義外掛的共同元素擴充套件元素集合主要包括以下的元素:Directories用於設定各種目錄結構,如下:  <build>    <source

統計學機器學習到底有什麽區別? - 機器學習研究會訂閱號

可視化 -type con 方程 分享圖片 創建 例如 大數 集合論 很有必要討論一下,爭論很大。 統計學和機器學習之間的界定一直很模糊。 無論是業界還是學界一直認為機器學習只是統計學批了一層光鮮的外衣。 而機器學習支撐的人工智能也被稱為&ldq

關於Tomcat的點點滴滴體系架構、處理http請求的過程、安裝配置、目錄結構、設置壓縮中文文件名的支持、以及Catalina這個名字的由來……等

https 設置 重啟 specific 調用 持久化數據 所在 original apps 轉自:http://itfish.net/article/41668.html 總結Tomcat的體系架構、處理http請求的過程、安裝和配置、目錄結構、設置壓縮和對中文文件名

python中xrangerange

log item .py 對象 nbsp net range all file 說到序列,我們第一想到的是一組有序元素組成的集合。同時,每個元素都有唯一的下標作為索引。 在Python中,有許多內界的序列。包括元組tuple,列表list,字符串str等。上面提到的序列

python閉包裝飾器

lee type ade 機制 並且 change -1 pri neu 一、python閉包 1、內嵌函數 >>> def func1(): ... print (‘func1 running...‘) ... def func2(

python 正則表達式中反斜杠()的麻煩陷阱 

[] 內部 ica con re模塊 .com 斜杠 字符 pat 這裏是一點小心得:由於下面兩個原因,在正則表達式中使用反斜杠就會產生了一個雙重轉換的問題。(1)、python自身處理字符串時,反斜杠是用於轉義字符 (2)、正則表達式也使用反斜杠來轉義字符

CStringstring在unicode與非unicode下的相互轉換

cst toc ref 編譯 end con adding eas font 原文轉自 http://blog.csdn.net/u014303844/article/details/51397556 CString和string在unicode與非unicode下的相

Python | 安裝配置智能提示插件Anaconda

主程序 content ima aid 默認 afa ssa 安裝路徑 建議 作為Python開發環境的Sublime Text 3,有了Anaconda就會如虎添翼。Anaconda是目前最流行也是最有威力的Python代碼提示插件。 工具/原料

python基礎學習-----生成器叠代器

分享 使用 生成 再次 流程 next 獨立 img eva 在Python中,很多對象都是可以通過for語句來直接遍歷的,例如list、string、dict等等,這些對象都可以被稱為可叠代對象。至於說哪些對象是可以被叠代訪問的,就要了解一下叠代器相關的知識了。 叠代器

大資料處理之道十分鐘學會Python

轉自:http://blog.csdn.net/u010700335/article/details/42025391,如侵刪 (0)目錄 快速學Python 和 易犯錯誤(文字處理) Python文字處理和Java/C比對 十分鐘學會Python的基本型別 快速學會Python(

Python中的X[:,0]、X[:,1]、X[:,:,0]、X[:,:,1]、X[:,m:n]X[:,:,m:n]

      Python中對於陣列和列表進行切片操作是很頻繁的,當然對於切片的操作可供我們直接使用的函式也是很遍歷了,我們今天主要簡單總結一下常用集中索引化方式,希望對大家有所幫助吧。           對於列表的切片比較簡單,在我之前的部落格裡面有詳細的講解,需要的話可

python 全棧開發,Day70(模板自定義標籤過濾器,模板繼承 (extend),Django的模型層-ORM簡介)

昨日內容回顧 檢視函式: request物件 request.path 請求路徑 request.GET GET請求資料 QueryDict {} request.POST POST請求資料 Que

Unicode中文轉換工具類方法

/* * 中文轉unicode編碼 */ public static String gbEncoding(final String gbString) { char[] utfBytes = gbString.toCharArray(); St

python selenium-webdriver 元素操作之滑鼠鍵盤事件

參考資料:https://blog.csdn.net/zh175578809/article/details/76767748 參考資料2:https://blog.csdn.net/qq_41817302/article/details/79618654   selenium 提供了比較完整的鍵盤操作,

Unicode字符集下CString與char *轉換 解決中文亂碼等

1、Unicode下CString轉換為char * 方法一:使用API:WideCharToMultiByte進行轉換              CStringstr = _T("D:\\校內專案\\QQ.bmp");             //注意:以下n和l