不知道大家有沒有想過一個問題,那就是為什麼要編碼?我們能不能不編碼?要回答這個問題必須要回到電腦是如何表示我們人類能夠理解的符號的,這些符號也就是我們人類使用的語言。由於人類的語言有太多,因而表示這些語言的符號太多,無法用電腦中一個基本的儲存單元—— byte 來表示,因而必須要經過拆分或一些翻譯工作,才能讓電腦能理解。我們可以把電腦能夠理解的語言假定為英語,其它語言要能夠在電腦中使用必須經過一次翻譯,把它翻譯成英語。這個翻譯的過程就是編碼。所以可以想象只要不是說英語的國家要能夠使用電腦就必須要經過編碼。這看起來有些霸道,但是這就是現狀,這也和我們國家現在在大力推廣漢語一樣,希望其它國家都會說漢語,以後其它的語言都翻譯成漢語,我們可以把電腦中儲存資訊的最小單位改成漢字,這樣我們就不存在編碼問題了。
所以總的來說,編碼的原因可以總結為:
- 電腦中儲存資訊的最小單元是一個位元組即 8 個 bit,所以能表示的字元範圍是 0~255 個
- 人類要表示的符號太多,無法用一個位元組來完全表示
- 要解決這個矛盾必須需要一個新的資料結構 char,從 char 到 byte 必須編碼
明白了各種語言需要交流,經過翻譯是必要的,那又如何來翻譯呢?計算中提拱了多種翻譯方式,常見的有 ASCII、ISO-8859-1、GB2312、GBK、UTF-8、UTF-16 等。它們都可以被看作為字典,它們規定了轉化的規則,按照這個規則就可以讓電腦正確的表示我們的字元。目前的編碼格式很多,例如 GB2312、GBK、UTF-8、UTF-16 這幾種格式都可以表示一個漢字,那我們到底選擇哪種編碼格式來儲存漢字呢?這就要考慮到其它因素了,是儲存空間重要還是編碼的效率重要。根據這些因素來正確選擇編碼格式,下面簡要介紹一下這幾種編碼格式。
學過電腦的人都知道 ASCII 碼,總共有 128 個,用一個位元組的低 7 位表示,0~31 是控制字元如換行斷行符號刪除等;32~126 是列印字元,可以通過鍵盤輸入並且能夠顯示出來。
128 個字元顯然是不夠用的,於是 ISO 組織在 ASCII 碼基礎上又制定了一些列標準用來擴充 ASCII 編碼,它們是 ISO-8859-1~ISO-8859-15,其中 ISO-8859-1 涵蓋了大多數西歐語言字元,所有應用的最廣泛。ISO-8859-1 仍然是單位元組編碼,它總共能表示 256 個字元。
它的全稱是《資訊交換用漢字編碼字元集 基本集》,它是雙位元組編碼,總的編碼範圍是 A1-F7,其中從 A1-A9 是符號區,總共包含 682 個符號,從 B0-F7 是漢字區,包含 6763 個漢字。
全稱叫《漢字內碼擴充規範》,是國家技術監督局為 windows95 所制定的新的漢字內碼規範,它的出現是為了擴充 GB2312,加入更多的漢字,它的編碼範圍是 8140~FEFE(去掉 XX7F)總共有 23940 個碼位,它能表示 21003 個漢字,它的編碼是和 GB2312 相容的,也就是說用 GB2312 編碼的漢字可以用 GBK 來解碼,並且不會有亂碼。
全稱是《資訊交換用漢字編碼字元集》,是我國的強制標準,它可能是單位元組、雙位元組或者四位元組編碼,它的編碼與 GB2312 編碼相容,這個雖然是國家標準,但是實際應用系統中使用的並不廣泛。
說到 UTF 必須要提到 Unicode(Universal Code 統一碼),ISO 試圖想建立一個全新的超語言字典,世界上所有的語言都可以通過這本字典來相互翻譯。可想而知這個字典是多麼的複雜,關於 Unicode 的詳細規範可以參考相應文檔。Unicode 是 Java 和 XML 的基礎,下面詳細介紹 Unicode 在電腦中的儲存形式。
UTF-16 具體定義了 Unicode 字元在電腦中存取方法。UTF-16 用兩個位元組來表示 Unicode 轉化格式,這個是定長的表示方法,不論什麼字元都可以用兩個位元組表示,兩個位元組是 16 個 bit,所以叫 UTF-16。UTF-16 表示字元非常方便,每兩個位元組表示一個字元,這個在字串操作時就大大簡化了操作,這也是 Java 以 UTF-16 作為記憶體的字元儲存格式的一個很重要的原因。
UTF-16 統一採用兩個位元組表示一個字元,雖然在表示上非常簡單方便,但是也有其缺點,有很大一部分字元用一個位元組就可以表示的現在要兩個位元組表示,儲存空間放大了一倍,在現在的網路頻寬還非常有限的今天,這樣會增大網路傳輸的流量,而且也沒必要。而 UTF-8 採用了一種變長技術,每個編碼地區有不同的字碼長度。不同類型的字元可以是由 1~6 個位元組組成。
UTF-8 有以下編碼規則:
- 如果一個位元組,最高位(第 8 位)為 0,表示這是一個 ASCII 字元(00 - 7F)。可見,所有 ASCII 編碼已經是 UTF-8 了。
- 如果一個位元組,以 11 開頭,連續的 1 的個數暗示這個字元的位元組數,例如:110xxxxx 代表它是雙位元組 UTF-8 字元的首位元組。
- 如果一個位元組,以 10 開始,表示它不是首位元組,需要向前尋找才能得到當前字元的首位元組。