1. 程式人生 > >Java編碼(一)——編碼基礎知識

Java編碼(一)——編碼基礎知識

在開發過程中我們往往會遇到很多中文亂碼的問題,而要解決這個問題無非抓住編碼和解碼的一致性問題,但理解其背後的原因及定位問題,還需要了解現有的編碼基礎知識。

一、專業詞彙

1.1 編碼與解碼

資料在計算機中儲存格式都是用0和1表示的。編碼是資訊從一種形式或格式轉換為另一種形式的過程,通俗點講就是就是將我們看到的文字、圖片等資訊按照某種規則儲存在計算機中;解碼是編碼的逆過程,它是將儲存在計算機的二進位制轉換為我們可以看到的文字、圖片等資訊,它體現的是視覺上的刺激。

在編碼和解碼中,他們就如加密、解密一般,他們一定會遵循某個規則,如果兩者規則不一致就會出現亂碼,這就是亂碼的根源。

1.2 字元

字元是可使用多種不同字元方案或內碼表來表示的抽象實體,它是一個單位的字形、類字形單位或符號的基本資訊,也是各種文字和符號的總稱,包括各國家文字、標點符號、圖形符號、數字等。

字元是指計算機中使用的字母、數字、字和符號,包括:1、2、3、A、B、C、~!·#¥%……—*()——+等等。在 ASCII 編碼中,一個英文字母字元儲存需要1個位元組。在 GB 2312 編碼或 GBK 編碼中,一個漢字字元儲存需要2個位元組。在UTF-8編碼中,一個英文字母字元儲存需要1個位元組,一個漢字字元儲存需要3到4個位元組。在UTF-16編碼中,一個英文字母字元或一個漢字字元儲存都需要2個位元組(Unicode擴充套件區的一些漢字儲存需要4個位元組)。

1.3 字符集(Charset)

字元是各種文字和符號的總稱,而字符集則是多個字元的集合,字符集種類較多,每個字符集包含的字元個數不同。而計算機要準確的處理各種字符集文字,需要進行相應的字元編碼,以便計算機能夠識別和儲存各種文字。

常見字符集名稱:ASCII字符集、GB2312字符集、BIG5字符集、 GB18030字符集、Unicode字符集等。

1.4 字元編碼(CharactorEncoding)

計算機中的資訊包括資料資訊和控制資訊,然而不管是那種資訊,他們都是以二進位制編碼的方式存入計算機中,但是他們是如何存放和顯示而不會出錯?這個時候字元編碼就起到了重要作用,字元編碼是一套規則

,一套建立在符合集合與數字系統之間的對應關係之上的規則,它是資訊處理的基本技術。

二、編碼標準

2.1 ASCII編碼

ASCII(American Standard Code for Information Interchange,美國資訊交換標準程式碼)是基於拉丁字母的一套電腦編碼系統。它主要用於顯示現代英語和其他西歐英語,它是現今最通用的單位元組編碼系統。

ASCII使用7位或者8位來表示128或者256種可能的字元。標準的ASCII碼則是使用7位二進位制數來表示所有的大小寫字母、數字、標點符合和一些控制字元,其中:

0~31、127(共33個)是控制字元或者通訊專用字元,如控制符:LF(換行)、CR(回車)、DEL(刪除)等;通訊專用字元:SOH(文頭)、EOT(文尾)、ACK(確認)等。ASCII值為8、9、10、13分別表示退格、製表、換號、回車字元。

32~126(共95個)字元,32為空格、48~57為阿拉伯數字、65~90為大寫字母、97~122為小寫字母,其餘為一些標點符號和運算子號!

 

2.2 GB系列編碼

對於歐美國家來說,ASCII能夠很好的滿足使用者的需求,但是我們的漢字達到將近10萬,顯示中文的常用字元編碼有:GB2312、GBK、GB18030。

1)GB2312

在GB2312中,GB2312共收錄6763個漢字,其中一級漢字3755個,二級漢字3008個,還收錄了拉丁字母、希臘字母、日文等682個全形字元。

2)GBK

GBK是GB2312的擴充套件,他向下與GB2312相容,,向上支援 ISO 10646.1 國際標準,是前者向後者過渡過程中的一個承上啟下的標準。同時它是使用雙位元組編碼方案,其編碼範圍從8140至FEFE(剔除xx7F),首位元組在 81-FE 之間,尾位元組在 40-FE 之間,共23940個碼位,共收錄了21003個漢字。

3)GB18030

2.3 Unicode及其實現

1)Unicode

Unicode又稱為統一碼、萬國碼、單一碼,它是為了解決傳統的字元編碼方案的侷限而產生的,它為每種語言中的每個字元設定了統一併且唯一的二進位制編碼,以滿足跨語言、跨平臺進行文字轉換、處理的要求。可以想象Unicode作為一個“字元大容器”,它將世界上所有的符號都包含其中,並且每一個符號都有自己獨一無二的編碼,這樣就從根本上解決了亂碼的問題。所以Unicode是一種所有符號的編碼[2]

Unicode為了和它們相互相容,其首256字元保留給ISO 8859-1所定義的字元,使既有的西歐語系文字的轉換不需特別考量;並且把大量相同的字元重複編到不同的字元碼中去,使得舊有紛雜的編碼方式得以和Unicode編碼間互相直接轉換,而不會丟失任何資訊[1]。

2)Unicode轉換格式

一個字元的Unicode編碼是確定的,但是在實際傳輸過程中,由於不同系統平臺的設計不一定一致,以及出於節省空間的目的,對Unicode編碼的實現方式有所不同。Unicode的實現方式稱為Unicode轉換格式(Unicode Transformation Format,簡稱為UTF)。

Unicode是字符集,它主要有UTF-8、UTF-16、UTF-32三種實現方式。由於UTF-8是目前主流的實現方式,UTF-16、UTF-32相對而言使用較少。

 

UTF-8

UTF-8是一種針對Unicode的可變長度字元編碼,可以使用1~4個位元組表示一個符號,根據不同的符號而變化位元組長度。它可以用來表示Unicode標準中的任何字元,且其編碼中的第一個位元組仍與ASCII相容,這使得原來處理ASCII字元的系統無須或只須做少部份修改,即可繼續使用。因此,它逐漸成為電子郵件、網頁及其他儲存或傳送文字的應用中,優先採用的編碼。

UTF-8使用一到四個位元組為每個字元編碼,編碼規則如下:

  • 對於單位元組的符號,位元組的第一位設為0,後面7位為這個符號的unicode碼。因此對於英語字母,UTF-8編碼和ASCII碼是相同的。
  • 對於n位元組的符號(n>1),第一個位元組的前n位都設為1,第n+1位設為0,後面位元組的前兩位一律設為10。剩下的沒有提及的二進位制位,全部為這個符號的unicode碼。

轉換表如下:

Unicode

UTF-8

0000 ~007F

0XXX XXXX

0080 ~07FF

110X XXXX 10XX XXXX

0800 ~FFFF

1110XXXX 10XX XXXX 10XX XXXX

1 0000 ~1F FFFF

1111 0XXX 10XX XXXX 10XX XXXX 10XX XXXX

20 0000 ~3FF FFFF

1111 10XX 10XX XXXX 10XX XXXX 10XX XXXX 10XX XXXX

400 0000 ~7FFF FFFF

1111 11010XX XXXX 10XX XXXX 10XX XXXX 10XX XXXX 10XX XXXX

根據上面的轉換表,理解UTF-8的轉換編碼規則就變得非常簡單了:第一個位元組的第一位如果為0,則表示這個位元組單獨就是一個字元;如果為1,連續多少個1就表示該字元佔有多少個位元組。

以漢字"嚴"為例,演示如何實現UTF-8編碼。

已知"嚴"的unicode是4E25(100111000100101),根據上表,可以發現4E25處在第三行的範圍內(0000 0800-0000 FFFF),因此"嚴"的UTF-8編碼需要三個位元組,即格式是"1110xxxx 10xxxxxx 10xxxxxx"。然後,從"嚴"的最後一個二進位制位開始,依次從後向前填入格式中的x,多出的位補0。這樣就得到了,"嚴"的UTF-8編碼是"11100100 10111000 10100101",轉換成十六進位制就是E4B8A5。