字符編碼學習筆記 (一)

1.從Txt看起

新建一個Txt文件,輸入字符“ab早”,選擇菜單另存爲,此時出現4個選項,見1

141625148.png

1

這是四種不同的編碼。


分別以這四種編碼來保存文件,並用二進制編輯器查看生成的文件,可以得到如下的結果。

編碼方式

用十六進制表示的文件內容

ANSI

141642673.png

Unicode

141723246.png

Unicode big endian

141734222.png

UTF-8

141803104.png

2

  (一)ANSI

ANSI編碼應該算是一套很龐大的體系。簡體中文GB2312,繁體中文BIG5等都只是ANSI的一個代碼頁。

什麼是代碼頁呢?打開Windows的控制面板->區域和語言,可以看到如下的選項。

141828462.png

3

這裏面每一個選項都是一個代碼頁。

也可以這麼說,如果系統語言選擇了中文(簡體,中國),那麼該系統中ANSI就代表GB2312編碼。同理,選擇中文(繁體,臺灣),那麼ANSI就代表BIG5編碼。

做個小實驗驗證一下。在簡體中文環境下,新建一個Txt文件輸入“ab早”,另存爲ANSI編碼。切換語言環境爲繁體中文(前提是裝過對應的語言包),系統要求重啓,確定。重啓之後,打開之前保存的Txt文件。顯示出來的內容變成了“ab婌”。‘早’的GB2312編碼是D4E7,‘婌’的BIG5編碼也是D4E7。這就驗證了之前所說的,同樣的數據用ANSI編碼,在不同的系統語言環境下,被解釋成了不同的字符。

另外,不論是ANSI編碼的哪個代碼頁,都是兼容ASCII碼的。也就是說,對於ASCII碼中的128個字符,在ANSI中也是用一個字節表示。其它字符都是用兩個字節表示的,並且這兩個字節都是大於0x7F的。

(二)Unicode

Unicode可以編碼大部分語言的大部分字符。在網上找資料的時候,有個問題一直在困擾着我。照理說,現在Unicode的編碼範圍是0-0x10FFFF,這已經是3個字節了,我疑惑的是爲什麼Unicode字符統一都是兩個字節呢?

繼續找資料。我得出的結論是此處的Unicode其實是Utf-16。好吧,大膽猜測,接下來還要小心求證。

求證之前,先來說說什麼是Utf-8Utf-16Utf-32(下面簡稱Utf-x)。Unicode只規定了從數字到字符的對應關係,並沒有規定具體的實現方法。因此Utf-x其實是Unicode的具體實現,當然也可以稱爲Unicode的再編碼。從UnicodeUtf-x是有具體的映射關係的,而且是有規律的映射關係,可以用一個簡單的函數來轉換。

開始求證吧。從UnicodeUtf-x的詳細映射方法,可點擊最下面的鏈接(Unicode)查看。這裏簡要說說Utf-16是怎麼映射的。Unicode編碼共有21位,當高5位爲0時,Unicode編碼和Utf-16相同,此時在Utf-16編碼中,一個字符佔2個字節。當高5位不爲0時,Unicode編碼經過映射變成了4個字節的Utf-16編碼,顯然這時一個字符佔4個字節。

先來驗證高5位爲0時的情況。之前已經試過,在Txt文件中輸入‘ab早’,另存爲UNICODE格式,用二進制編輯器查看,發現‘早’的編碼是“E965”。在Unicode詳細編碼表中查找(下有鏈接),要注意這裏存儲方式是小尾的,也就是說‘早’的真正編碼是65E9

結果我就不貼了,‘早’字確實在編碼表的那個位置。

再來驗證高5位不爲0時的情況。先找個Unicode編碼大於0xFFFF的字符(有些範圍內的字符顯示出來都是方框,估計我的電腦上就沒有這種字符)。用來做實驗的字符見下圖。141854924.png

4

選用編碼爲0x20001的那個字符(Word上顯示不了這個字符,Txt上面倒是可以)。複製這個字符到Txt中,另存爲Unicode,再用二進制編輯器打開。結果如下:

141906844.png

5

編碼後的長度是4個字節,這個已經對上了,再看看具體的值對不對。算吧!

      1.U= 0x20001

      2.U’= U – 0x10000 = 0x10001 = 0001 0000 0000 0000 0001

      3.Utf-16= 1101 1000 0100 0000 1101 1100 0000 0001 = 0xD840DC01

      4.考慮到以小尾方式存儲 Utf-16’ = 0x40D801DC

      5.是不是和上圖中的數字對上了啊!

現在大體上已經可以確認Txt中這個所謂的Unicode其實就是Utf-16,或者至少是一個和Utf-16兼容的編碼。

最後說說FFFEFEFF。可以看到當將Txt保存爲Unicode編碼的時候,不論大小尾,在正式字符編碼開始之前,都會有FFFEFEFF。這個是用來表示字節序的,FFFE是小尾字節序,FEFF是大尾字節序。

  (三)Unicode big endian

除了字節序採用大尾之外,其它的都和Unicode一樣。

(四)UTF-8

UTF-8也是UNICODE編碼的一個具體實現方式。UTF-8的特點是變長編碼(1~4個字節),對於0x00~0x7F之間的編碼與ASCII碼完全相同,而漢字一般情況下編碼長度是3個字節。那麼下面動手求求‘早’字的UTF-8編碼是多少吧!

1.U = 0x65E9 = 01100101 1110 1001

2.套用第三個模板

3.Utf-8 = 11100110 1001 0111 1010 1001 = 0xE697A9

   4.對照 2,結果是對的。

此外可以發現,UTF-8格式的文件,在正式編碼之前也有個標記,EFBBBF,這個是UTF-8文件頭,用來告訴別人接下來的數據是UTF-8編碼。



相關資料:

http://baike.baidu.com/link?url=lqme-rGBqK9t9DbwPv5tm-CDPXKaxYYIOMbrvZncYiRWgFEokJlMhJ8E-Yd7AVARfv0TY03-JrmHf_kKLek3Ta  -----  ANSI

http://blog.csdn.net/xiongxiao/article/details/3741731  -----  多種編碼

http://baike.baidu.com/link?url=yxnWqjaIlBpMMenb3gmQtX5thFAds4ysiSgE-HS-lS8qwpsYNYrsdRLM8zrEKXou   ----- 代碼頁

http://baike.baidu.com/link?url=Op9QHQGnv97slgXaB7YpEsEo_GW3KRfm-Nf202xELyCpcKHacc5xKUvlqvB2Hjlu    -----   Unicode

http://zh.wikibooks.org/wiki/Unicode/0000-0FFF     ----- Unicode詳細編碼表

http://wenku.baidu.com/link?url=3JS_YTGkFlNZjWSuJRJjdsD0qmddmNr8qV-f1ZzJKgWYdlCco4eDMVhSaA6Qswj_Fxdw69FB2WY2UmXeDDqtnaZUr82Edfag94LH_1v8RbO

-----   GB2312編碼表

http://wenku.baidu.com/link?url=9_KJEIm1skZsvmXAZIWyKP8hlybcyWtN7WqOHLYxwdsQMvAbaSRD8Gx4fMd3_PLypd6bmnMhgMmUmd3fq55S3Ip6FXF8D81aesZGkiQtOFS

-----   BIG5編碼表




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章