字元編碼前世今生詳解,從此與“亂碼”說再見!

ai3707發表於2016-03-30
    大家在做web開發的時候是不是經常被亂碼問題所困擾?做運維的DBA,oracle資料庫使用ogg時也出現過“亂碼”問題吧?這的確是個讓人頭痛的問題,有時候調整一下字符集就解決了,有時候又出現了,本人也在開發和運維工作中遇到過多次“亂碼”問題,一直懵懵懂懂,知其然不知其所以然,最近終於下定決心好好的學下字元編碼,小有成果,分享給大家,如有不足之處還請多多指正,共同進步!

   那麼什麼是字元編碼呢?這裡我們將它拆分開,1、字符集   2、編碼。

   字符集:是一個系統支援的所有抽象字元的集合。字元是各種文字和符號的總稱,包括各國家文字、標點符號、圖形符號、數字等。
   字元編碼:是一套法則,使用該法則能夠對自然語言的字元的一個集合(如字母表或音節表),與其他東西的一個集合(如號碼或電脈衝)進行配對。即在符號集合與數字系統之間建立對應關係,它是資訊處理的一項基本技術。通常人們用符號集合(一般情況下就是文字)來表達資訊。而以計算機為基礎的資訊處理系統則是利用元件(硬體)不同狀態的組合來儲存和處理資訊的。元件不同狀態的組合能代表數字系統的數字,因此字元編碼就是將符號轉換為計算機可以接受的數字系統的數,稱為數字程式碼。

      以上為官方解釋,字符集大家好理解,字元編碼是不是看暈了?我說說我通俗的理解:字元編碼就是把我們所有人類建立的字元,比如:“數字、字母、文字、特殊符號等”讓計算機認識並且能存取,可是計算機大家都知道只認識二進位制0和1,所以說需要進行編碼,也就是透過約定好的一種方式將字元轉化為0和1的組合儲存在計算機中,目前編碼方式全世界有多種多樣,後面會介紹,而從計算機中取出這些字元時就需要解碼,當然也是透過與編碼時相同的規則取資料,如果存數和取數的編碼方式不對,就會出現牛頭不對馬嘴或者是鳥文“*&@930*@#*7284”,呵呵,好理解吧!
     再舉個例子,抗戰時期,我軍與日寇都需要電臺,以便於傳送電報給友軍及時彙報戰況或訊息,而那個年代科技並不發達無限電臺頻道數量有限,有時候不得不公用一個頻道發電報,這就出現了一個問題,電報內容被竊取了怎麼辦?所以就發明了密碼本,根據己方的密碼本再翻譯電臺裡傳送來的資訊,就拿到了戰報,而敵人則無法破解。在這裡密碼本就相當於我們現在說的編碼規則,寫入資料是按照指定的編碼規則寫的,則取數時就要按照約定好的編碼規則取,否則就要取到“亂碼”;那麼,現在又不需要保密,為什麼不全世界公用一種編碼規則呢? 別急,下面我仔細介紹下各個編碼規則

1、追溯——ASCII編碼
    首先,發明計算機的人最開始肯定沒想到計算機會應用的這麼廣泛!在目前我們大多數計算機中都是ASCII編碼,通俗的解釋ASCII碼,就是鍵盤!你的鍵盤上這些字母數字回車特殊符號等都屬於ASCII碼,他可以基本上表示通用英語,可能發明計算機的人覺得這些已經足夠了,於是設計了一個編碼規則,規定:ASCII編碼由8位表示一個字元,也就是:0000000——11111111,大小範圍限定好了,然後指定了一套規則,如下:
                                
    呵呵,後面還有一張ASCII編碼擴充圖,我就不貼上去了,看著煩,哈哈~  其實,沒什麼卵用大家平時工作也不需要關心具體編碼規則怎麼實現的,需要記住的是:ASCII編碼是遠遠滿足不了人類需求的,因為8位的大小並不足以表達這個美好的世界上的所有事物,比如說一個我大天朝的30劃的漢字。。。在這個背景下,各種的編碼規則應運而生~~~~以我大天朝為例,就有GB2312GB2312GB2312-80、GBK各種編碼規則和字符集,像天朝一樣,當計算機傳到世界各個國家時,為了適合當地語言和字元,設計和實現類似GB232/GBK/GB18030/BIG5的編碼方案。這樣各搞一套,在本地使用沒有問題,一旦出現在網路中,由於不相容,互相訪問就出現了亂碼現象。在這種環境下,偉大的unicode誕生了

2、
unicode編碼/字符集
    為了使國際間資訊交流更加方便,國際組織制定了 UNICODE 字符集,為各種語言中的每一個字元設定了統一併且唯一的數字編號,以滿足跨語言、跨平臺進行文字轉換、處理的要求。
在 UNICODE 被採用之後,計算機存放字串時,改為存放每個字元在 UNICODE 字符集中的序號。目前計算機一般使用 2 個位元組(16 位)來存放一個序號(DBCS,Double Byte Character System),因此,這種方式存放的字元也被稱作寬位元組字元。比如,字串 "中文123" 在 Windows 2000 下,記憶體中實際存放的是 5 個序號,一共10個位元組。Unicode字符集包含了各種語言中使用到的所有“字元”。用來給 UNICODE 字符集編碼的標準有很多種,比如:UTF-8, UTF-7, UTF-16, UnicodeLittle, UnicodeBig 等。

3、UTF-8編碼
  終於字符集統一了,那我介紹一下應用最廣泛的UTF-8編碼方式:
UCS-2編碼(16進位制)   UTF-8 位元組流(二進位制)
0000 - 007F         0xxxxxxx
0080 - 07FF         110xxxxx 10xxxxxx
0800 - FFFF         1110xxxx 10xxxxxx 10xxxxxx 
例如“漢”字的Unicode編碼是6C49。6C49在0800-FFFF之間,所以肯定要用3位元組模板了:1110xxxx 10xxxxxx 10xxxxxx。將6C49寫成二進位制是:0110 110001 001001,用這個位元流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。
可見UTF-8是變長的,將Unicode編碼為00000000-0000007F的字元,用單個位元組來表示; 00000080-000007FF的字元用兩個位元組表示;00000800-0000FFFF的字元用3位元組表示。因為目前為止Unicode-16規範沒有指定FFFF以上的字元,所以UTF-8最多是使用3個位元組來表示一個字元。但理論上來說,UTF-8最多需要用6位元組表示一個字元。,UTF-8相容ASCII。
總結來說:採用UTF-8編碼方式,漢字佔24位也就是3位元組,字母數字特殊符號佔8位也就是1位元組。UTF-8國際通用,你要不想你的網站在國外訪問時全是亂碼的話,那就採用UTF-8編碼吧,哈哈

4、GB2312、GBK和GB18030編碼
   在我大天朝的網站中,使用GBK編碼的還是大有人在,
(1)GB2312 
    當中國人們得到計算機時,已經沒有可以利用的位元組狀態來表示漢字,況且有6000多個常用漢字需要儲存,於是想到把那些ASCII碼中127號之後的奇異符號們直接取消掉, 規定:一個小於127的字元的意義與原來相同,但兩個大於127的字元連在一起時,就表示一個漢字,前面的一個位元組(稱之為高位元組)從0xA1用到0xF7,後面一個位元組(低位元組)從0xA1到0xFE,這樣我們就可以組合出大約7000多個簡體漢字了。在這些編碼裡,我們還把數學符號、羅馬希臘的字母、日文的假名們都編進去了,連在 ASCII 裡本來就有的數字、標點、字母都統統重新編了兩個位元組長的編碼,這就是常說的"全形"字元,而原來在127號以下的那些就叫"半形"字元了。這種漢字方案叫做 "GB2312"。GB2312 是對 ASCII 的中文擴充套件。相容ASCII。
(2)GBK 
   但是中國的漢字太多了,我們很快就就發現有許多人的人名沒有辦法在這裡打出來,不得不繼續把 GB2312 沒有用到的碼位找出來用上。後來還是不夠用,於是乾脆不再要求低位元組一定是127號之後的內碼,只要第一個位元組是大於127就固定表示這是一個漢字的開始,不管後面跟的是不是擴充套件字符集裡的內容。結果擴充套件之後的編碼方案被稱為 “GBK” 標準,GBK 包括了 GB2312 的所有內容,同時又增加了近20000個新的漢字(包括繁體字)和符號。
 (3)GB18030 
   後來少數民族也要用電腦了,於是我們再擴充套件,又加了幾千個新的少數民族的字,GBK 擴成了 GB18030。從此之後,中華民族的文化就可以在計算機時代中傳承了。 
總結來說:採用GBK編碼方式,漢字和字母都是佔24位2位元組,如果你的網站只在國內使用並且漢字很多的情況下可以考慮使用GBK編碼,可以節省儲存空間;其他編碼方式也很多,就不一一介紹了





來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29018063/viewspace-2072599/,如需轉載,請註明出處,否則將追究法律責任。

相關文章