前兩天看了一篇講python編碼的文章,感覺收穫了不少,裏面提到了幾個概念,感覺對理解編碼很有幫助。
字符序列:"禪"
字節序列: \xec\xf8(十六進制);11101100 11111000(二進制)
編碼:禪(字符)→11101100 11111000(字節)
解碼:11101100 11111000(字節)→禪(字符)
===========================以下是原文=======================
寫在前面。字符編碼是一個讓人頭疼的問題,讓問題顯得混淆的原因不止在於編碼本身的多樣性和發展變化,更在於人們對於其中所涉及的術語概念的濫用。本文所提到的術語概念是在查閱相關資料以及文獻彙總得到的,注重於對編碼所涉及的問題的梳理。
一、基本概念
字符集:一個國家或地區,或者某種語言文字中所使用的所有符號的集合。如中國字符集指的就是“漢字”和標點。
字符編碼:一個從字符集到一個非負整數集合直接的一一映射,經常使用一個表格給出。
字符編碼算法:把字符對應的字符編碼映射爲八位組序列的方法。
注:有的文獻也將字符編碼和字符編碼算法統稱爲“編碼”,即規定每個“字符”分別用一個字節還是多個字節存儲,用哪些字節來存儲。事實上,各個國家和地區在制定編碼標準的時候,“字符編碼”和“編碼算法”一般都是同時制定的。因此,平常我們所說的“字符編碼”,比如:GB2312, GBK, JIS 等,除了有“字符的集合”這層含義外,同時也包含了“編碼方法”的含義。
二、字符編碼發展階段
從計算機對多國語言的支持角度看,字符編碼的發展大致可以分爲三個階段(下表出處見參考資料2):
系統內碼 | 說明 | 系統 | |
階段一 | ASCII | 計算機剛開始只支持英語,其它語言不能夠在計算機上存儲和顯示。 | 英文 DOS |
階段二 |
ANSI編碼 (本地化) |
爲使計算機支持更多語言,通常使用 0x80~0xFF 範圍的 2 個字節來表示 1 個字符。比如:漢字 '中' 在中文操作系統中,使用 [0xD6,0xD0] 這兩個字節存儲。 不同的國家和地區制定了不同的標準,由此產生了 GB2312, BIG5, JIS 等各自的編碼標準。這些使用 2 個字節來代表一個字符的各種漢字延伸編碼方式,稱爲 ANSI 編碼。在簡體中文系統下,ANSI 編碼代表 GB2312 編碼,在日文操作系統下,ANSI 編碼代表 JIS 編碼。 不同 ANSI 編碼之間互不兼容,當信息在國際間交流時,無法將屬於兩種語言的文字,存儲在同一段 ANSI 編碼的文本中。 |
中文 DOS,中文 Windows 95/98,日文 Windows 95/98 |
階段三 |
UNICODE (國際化) |
爲了使國際間信息交流更加方便,國際組織制定了 UNICODE 字符集,爲各種語言中的每一個字符設定了統一併且唯一的數字編號,以滿足跨語言、跨平臺進行文本轉換、處理的要求。 | Windows NT/2000/XP,Linux,Java |
理解編碼的關鍵,還要把字符的概念和字節的概念理解準確。這兩個概念容易混淆,我們在此做一下區分(參考資料2):
概念描述 | 舉例 | |
字符 | 人們使用的記號,抽象意義上的一個符號。 | '1', '中', 'a', '$', '¥', …… |
字節 | 計算機中存儲數據的單元,一個8位的二進制數,是一個很具體的存儲空間。 | 0x01, 0x45, 0xFA, …… |
ANSI 字符串 |
在內存中,如果“字符”是以 ANSI 編碼形式存在的,一個字符可能使用一個字節或多個字節來表示,那麼我們稱這種字符串爲 ANSI 字符串或者多字節字符串。 |
"中文123" (佔7字節) |
UNICODE 字符串 |
在內存中,如果“字符”是以在 UNICODE 中的序號存在的,那麼我們稱這種字符串爲 UNICODE 字符串或者寬字節字符串。 |
L"中文123" (佔10字節) |
由於不同 ANSI 編碼所規定的標準是不相同的,因此,對於一個給定的多字節字符串,我們必須知道它採用的是哪一種編碼規則,才能夠知道它包含了哪些“字符”。也就是說,以字節形式存在的字符串,必須知道是哪種編碼才能被正確地使用。而對於 UNICODE 字符串來說,是以字符的“序號”來存儲的,不管在什麼環境下,它所代表的“字符”內容總是不變的。
三、具體實例
在這裏,我們根據編碼規則的特點,把所有的編碼分成三類(同樣來自資料2):
分類 | 編碼方法 | 說明 |
單字節字符編碼 | ISO-8859-1 |
最簡單的編碼規則,每一個字節直接作爲一個 UNICODE 字符。比如,[0xD6, 0xD0] 這兩個字節,通過 iso-8859-1 轉化爲字符串時,將直接得到 [0x00D6, 0x00D0] 兩個 UNICODE 字符,即 "ÖÐ"。 反之,將 UNICODE 字符串通過 iso-8859-1 轉化爲字節串時,只能正常轉化 0~255 範圍的字符。 |
ANSI 編碼 |
GB2312, BIG5, Shift_JIS, ISO-8859-2 …… |
把 UNICODE 字符串通過 ANSI 編碼轉化爲“字節串”時,根據各自編碼的規定,一個 UNICODE 字符可能轉化成一個字節或多個字節。 反之,將字節串轉化成字符串時,也可能多個字節轉化成一個字符。比如,[0xD6, 0xD0] 這兩個字節,通過 GB2312 轉化爲字符串時,將得到 [0x4E2D] 一個字符,即 '中' 字。 “ANSI 編碼”的特點: 1. 這些“ANSI 編碼標準”都只能處理各自語言範圍之內的 UNICODE 字符。 2. “UNICODE 字符”與“轉換出來的字節”之間的關係是人爲規定的。 |
UNICODE 編碼 |
UTF-8, UTF-16, UnicodeBig …… |
與“ANSI 編碼”類似的,把字符串通過 UNICODE 編碼轉化成“字節串”時,一個 UNICODE 字符可能轉化成一個字節或多個字節。 與“ANSI 編碼”不同的是: 1. 這些“UNICODE 編碼”能夠處理所有的 UNICODE 字符。 2. “UNICODE 字符”與“轉換出來的字節”之間是可以通過計算得到的。 |
我們實際上沒有必要去深究每一種編碼具體把某一個字符編碼成了哪幾個字節,我們只需要知道“編碼”的概念就是把“字符”轉化成“字節”就可以了。對於“UNICODE 編碼”,由於它們是可以通過計算得到的,因此,在特殊的場合,我們可以去了解某一種“UNICODE 編碼算法”是怎樣的規則。
參考資料:
1.李曉明等著.搜索引擎——原理、技術與系統.科學出版社.50-59.
2.字符,字節和編碼.注:本文所提到的概念和此鏈接內提到的略有不同。