二.關於字符編碼

上一次我們討論了Byte的詳細內容,這一次關於字符編碼的討論無疑是要建立在這基礎之上了。
1.ASCII(American Standard Code for Information Interchange)
在學習C語言中,我們接觸了最基本的一種編碼格式:ASCII碼。在計算機發明之初,一羣美國人在心裏琢磨,我們要在計算機上能顯示我們的語言,我們的文字,就必須要把所有的英語字母,符號以及阿拉伯數字用一些二進制序列表示出來。這樣,計算機看到的是二進制的編碼,對應的是人能看懂的語言。一個符號對應一個號碼。於是,美國人用一個字節(8 bit)來表示他們平時需要用到的字母,符號,數字等,1字節共有256種組合(00-FF)由於英語字母大小寫一共只有52個,常用符號也有限,再加上一些常用的控制符,美國人只用了其中的128個(0-127)來編碼,這就是最基本的ASCII碼。(只用了128個,在上一次關於Byte的討論中,我們應該能知道,這說明ASCII在8 bit的第八位永遠是0)。
    
後來,計算機發展很快,全世界很多地方人都不使用英語。於是,他們果斷利用了ASCII未使用的剩下的128個字符,來表示他們的字母,符號。大家都感覺這樣很好。
    
    
2.GB(國標碼)
後來中國人開始用計算機,中國人發現,我們已經沒有可以利用的字符編碼來表示漢字了。況且,中國常用字就有6000多個,1 Byte只有256種組合,這根本就是供不應求啊。但這難不倒中國人,我們果斷把1 Byte中的後128個字符去掉,前128個沿用ASCII字符。並且我們用兩個字節表示一個漢字。這兩個字節的值都大於127。中國人感覺這樣不錯,於是我們把這種編碼方案叫做“GB2312”,在GB2312中,我們也把英語字母,數字等編了進去。這樣,同一個字母如果用GB碼錶示我們稱作"全角"字符,如果用ASCII碼錶示,就是"半角"字符。輸入法中有一個圓月和缺月的切換,指的就是全角字符和半角字符的切換。顯示的效果也是完全不同的。
    
後來我們感覺漢字太多了,而且包括很多繁體字,於是我們毫不猶豫地規定,只要2字節字符編碼的第一個字節大於127,就表示這個字節和後一個字節共同表示一個漢字,即使後一個字節是小於128的。這樣,我們有了128*256個空間可以表示漢字,我們不僅加入了繁體字,還加入的少數名族的符號。我們把這種方案叫做GBK編碼,後來GBK又被擴展成了GB18030。現在,大家應該知道了"爲什麼一個漢字算兩個英文字符?爲什麼一個漢字包含兩個字節?"了吧。
    
    
3.Unicode(Universal Multiple-Octet Coded Character Set)
如中國一樣,全世界很多國家都開發了一套屬於自己的字符編碼方式,這就帶來了一個問題,當一臺計算機需要切換使用不同的語言系統時,他們如何區分這些不同的編碼方案帶來的字符衝突問題呢?在GB碼中的漢字在別的編碼中表示的也許是別的符號。
    
這時,一個很權威的組織站了出來,他就是ISO——國際標準化組織,他們制定了很多標準以解決這些衝突問題,這次也不例外。他們的方法是這樣的,廢了所有的地區性編碼方案,重新搞一個包括了地球上所有文化、所有字母和符號的編碼!他們叫它"Universal Multiple-Octet Coded Character Set",簡稱 UCS,俗稱 "UNICODE"。Unicode用2字節的空間表示一個字符,一共可以表示65536個字符,這是UCS-2方案,爲了防止不夠用,ISO還制定了UCS-4方案,也就是用4個字節表示一個符號。這樣編碼得到的字符恐怕是用不完了吧。說到這兒我想插一句,經常我們打開一個文本文件或者一封郵件時,會看到一些亂碼,看不懂的符號,原因就是因爲文件保存與打開(郵件發送與接收)的編碼方式不同,那麼計算機當然就把原來的編碼翻譯成了我們看不懂的符號了。
    
    
4.UTF(UCS Transfer Format)
UTF是Unicode的一種實現形式,在互聯網中應用十分廣泛。UTF-8是應用最廣的實現方式,其他的實現方式還包括UTF-16和UTF-32。通過UTF的名字我們也能理解出,UTF是爲了適應比特流在網絡中傳輸而產生的標準,UTF-8就是每次傳輸8位,UTF-16就是每次傳輸16位,UTF-32就是32位。那麼現在我們來深入討論一下Unicode和UTF-8之間是如何轉換的。
    
(1)對於單字節的符號,字節的第一位設爲0,後面7位爲這個符號的unicode碼。因此對於英語字母,UTF-8編碼和ASCII碼是相同的。
(2)對於n字節的符號(n>1),第一個字節的前n位都設爲1,第n+1位設爲0,後面字節的前兩位一律設爲10。剩下的沒有提及的二進制位,全部爲這個符號的unicode碼。
具體點說:
Unicode              | UTF-8編碼方式
(十六進制)            | (二進制)
---------------------+-----------------------------------
0000 0000-0000 007F  | 0xxxxxxx
0000 0080-0000 07FF  | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF  | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF  | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
舉個例子,“嚴”的unicode是4E25(100 1110 0010 0101二進制),根據上表,可以發現4E25處在第三行的範圍內(0000 0800-0000 FFFF),因此“嚴”的UTF-8編碼需要三個字節,即格式是“1110xxxx 10xxxxxx 10xxxxxx”。然後,從“嚴”的最後一個二進制位開始,依次從後向前填入格式中的x,多出的位補0。這樣就得到了,“嚴”的UTF-8編碼是“11100100 10111000 10100101”,轉換成十六進制就是E4B8A5。
    
每次談及編碼必提一個著名的Bug,就是在Windows系統下,新建記事本,只寫入“聯通”二字,保存,關閉再打開會發現顯示亂碼,爲什麼呢?出現亂碼我之前說過一定是文件內容的保存與打開的編碼方式不同。
記事本的默認編碼方式是ANSI,在ANSI下敲入中文時用的是GB2312編碼,“聯通”在GB2312下的字符碼是C1AA CDA8
11000001 10101010 | 11001101 10101000
可以看出,這一段內碼的兩個部分正好都符合UTF-8的二字節格式,因此記事本會自動以UTF-8讀取文本,將其轉換成Unicode碼,而第二部分轉換成Unicode後不表示任何符號,因此無法正常顯示。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章