1. 程式人生 > >Python筆記:字元編碼unicode/utf-8

Python筆記:字元編碼unicode/utf-8

請尊重原創作品。轉載請保持文章完整性,並以超連結形式註明原始作者“tingsking18”和主站點地址,方便其他朋友提問和指正。

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和香港擴充套件版本)。雖
然同一派系的編碼可以向下相容,但考慮到其字元數目龐大,為了加快查詢速度,筆者個
人認為還是將它們分開編碼比較合理。當然,如果能夠找到對應字符集的轉換公式,則這
種分離就沒有必要了;

相關推薦

Python筆記字元編碼unicode/utf-8

請尊重原創作品。轉載請保持文章完整性,並以超連結形式註明原始作者“tingsking18”和主站點地址,方便其他朋友提問和指正。 Unicode和Python的中文處理   在Python語言中,Uincode字串處理一直是一個容易讓人迷惑的問題。許多Python

Mac電腦使用解決Mac上“文字編碼Unicode(UTF-8)不適用”、文字編碼“中文 (GB 18030)不適用“的問題

在Mac電腦上面開啟txt檔案,有些時候由於格式不一樣或者其他原因,會打不開txt檔案,這樣就需要我們對文字編輯的偏好設定裡面進行修改即可。這裡我只說兩種打不開的情況,這兩種情況就是標題說的這兩種情況。 一、先介紹第一種情況:未能開啟文稿“docs(1).txt”。文字編碼“Unicode(

python字元編碼:coding utf-8, unicde, defaultencoding, UnicodeDecodeError, UnicodeEncodeError

2.位元組與字元 計算機儲存的任何資料,包括各種文字、圖片、音視訊檔案等等,實際上都是一串二進位制數字01位元組序列組成的。相信大家都知道,一個位元組Byte(B)是8個位元bit(b)。 而字元,自然就是符號了。比如說二十六個英文字母,阿拉伯數字,以及在pyt

python2和python3字元編碼utf-8,unicode

二進位制 -> 轉換 -> 字串 需要解碼 decode字串 -> 轉換 -> 二進位制 需要編碼 encodepython3 記憶體中使用的字串全部是unicode碼,但是網路傳輸的資料或者從磁碟讀取的資料是把unicode碼轉換過的資料,通常情況下可能是utf-8格式的資料,所以如

Python2.7 中文字元編碼 & Pycharm utf-8設定、Unicodeutf-8的區別

Python2.7 中文字元編碼 & Pycharm utf-8設定、Unicode與utf-8的區別 [email protected] 作者:Zhouwan  2017-6-6  一、關於編碼和亂碼,有以下幾個重要的概念需要搞清楚:     二、Pycharm 設定編碼, 可以

Pycharm中設定預設字元編碼utf-8

呃...又來水一篇 為什麼要預設使用utf-8編碼 為了避免亂碼問題,我們統一用utf-8編碼。由於Python原始碼也是一個文字檔案,所以當你的原始碼包含中文的時候,在儲存原始碼的時候就務必指定儲存為UTF-8編碼。為了讓Python直譯器讀取原始碼的時候,能夠按utf-8編碼讀取,我

文字檔案轉換字元編碼UTF-8等)的通用方法

在windows的本身系統中,是難以知道一個檔案的編碼格式的。需要能過一些操作才能得知檔案的編碼格式。如果你沒有一些其他的工具來幫助你檢視檔案編碼格式,使用記事本也是可以達到目的。(在用到linux系統的時候,經常需要檢查或轉換文的編碼格式。linux如果中文的編碼格式不為

將.txt檔案用Mac開啟報文字編碼Unicode(UTF-8)”不適用的解決辦法

        蘋果電腦 Mac OS X 系統上雙擊 txt 檔案(尤其是 PC 傳過來的),會彈出「未能開啟文稿XXX,編碼"Unicode(UTF-8)不適用」的警告。一個純文字檔案,就是打不開

字元編碼筆記ASCII,UnicodeUTF-8

今天中午,我突然想搞清楚 Unicode 和 UTF-8 之間的關係,就開始查資料。 這個問題比我想象的複雜,午飯後一直看到晚上9點,才算初步搞清楚。 下面就是我的筆記,主要用來整理自己的思路。我儘量寫得通俗易懂,希望能對其他朋友有用。畢竟,字元編碼是計算機技術的基石,想要熟練使用計算機,就必須懂得一點字元編

字元編碼筆記ASCII,UnicodeUTF-8

今天中午,我突然想搞清楚Unicode和UTF-8之間的關係,於是就開始在網上查資料。 結果,這個問題比我想象的複雜,從午飯後一直看到晚上9點,才算初步搞清楚。 下面就是我的筆記,主要用來整理自己的思路。但是,我儘量試圖寫得通俗易懂,希望能對其他朋友有用。畢竟,字元編

字符編碼筆記ASCII,UnicodeUTF-8

evel IE 閑置 for 之一 問題: window bit tar 作者: 阮一峰 日期: 2007年10月28日 今天中午,我突然想搞清楚 Unicode 和 UTF-8 之間的關系,就開始查資料。 這個問題比我想象的復雜,午飯後一直看到晚上9點,才算初步搞清楚

[轉]字符編碼筆記ASCII,UnicodeUTF-8

中文編碼 new fff notepad absolut 歐洲 簡體中文 戰爭 遊記 本文非原創,轉載 ,原文地址 :http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html 作者: 阮

Python中的Unicode編碼UTF-8編碼

2個 傳輸 硬盤 中文字符 結合 2.7 客戶端 有一點 來看 下午看廖雪峰的Python2.7教程,看到 字符串和編碼 一節,有一點感受,結合 崔慶才的Python博客 ,把這種感受記錄下來: ASCII碼:是用一個字節(8bit, 0-255)中的127個字母表示大

關於編碼之一Unicode/UTF-8/UTF-16/UTF-32

規則 系統默認 標記 大小端 post mark 編碼方式 一位 end 1.關於編碼,繞不開下面這些概念 ①Unicode/UTF-8/UTF-16/UTF-32 ②大小端字節序(big-endian/little-endian) ③BOM(Byte Order M

Python基礎】字符編碼ASCII-GBK-Unicode-UTF-8之間的關系

精準 應該 寫入 歷程 UC tran 執行 文件 總結 字符編碼 由於計算機只識別0和1,為了使計算機能夠支持文字和字母等符號,方便實用操作計算機 於是字符編碼應運而生,旨在解決符號和人類語言與計算機0和1建立起一種對應關系 據說不理解字符編碼可能是程序員一輩子的遺憾,拿

python中的字符串編碼問題——2.理解ASCII碼、ANSI碼、Unicode編碼UTF-8編碼

unicode編碼 統一 col 簡單 utf 文字 stand 二進制 pan ASCII碼:全名是American Standard Code for Information Interchange,ASCII碼中,一個英文字母(不分大小寫)占一個字節的空間,範圍0x0

徹底搞懂字元編碼(unicode,mbcs,utf-8,utf-16,utf-32,big endian,little endian...)

最近有一些朋友常問我一些亂碼的問題,和他們交流過程中,發現這個編碼的相關知識還真是雜亂不堪,不少人對一些 知識理解似乎也有些偏差,網上百度,google的內容,也有不少以訛傳訛,根本就是錯誤的(例如說 unicode編碼是兩 個位元組),各種軟體讓你選擇編碼的時候,常

字元編碼之Ascll編碼,ANSI編碼Unicode編碼UTF-8編碼 ,BOM

從大一上C語言就開始認識了Ascll編碼,ascll碼也算是我們最早所接觸的編碼 【1】Ascll碼  Ascll碼由三部分組成:           第一部分從00H到1FH共32個,一般用來通訊或作為開工至之用,有的可以顯示在螢幕上,有的則無法再螢幕上顯示。  

python編碼轉換 unicode, utf-8, utf-16, GBK

GB 碼,全稱是GB2312-80《資訊交換用漢字編碼字符集基本集》,1980年釋出,是中文資訊處理的國家標準,在大陸及海外使用簡體中文的地區(如新加坡等)是強制使用的唯一中文編碼。P- Windows3.2和蘋果OS就是以GB2312為基本漢字編碼, Windows 95/98則以GBK為基本漢字編碼

各種字元編碼方式詳解及由來(ANSI,UNICODE,UTF-8,GB2312,GBK)

    一直對字元的各種編碼方式懵懵懂懂,什麼ANSI、UNICODE、UTF-8、GB2312、GBK、DBCS、UCS……是不是看的很暈,假如您細細的閱讀本文你一定可以清晰的理解他們。Let's go!                很久很久以前,有一群人,他們決定用8個可以開合的電晶體來組合成不同的狀