ASCII、GBK、Unicode、UTF-八、ISO-8859-1等常見字符編碼介紹

經過計算機編碼的誕生和發展歷程,理解爲毛有這麼多種字符編碼,以及他們之間的區別。本文主要參考網頁編碼就是那點事,並進行適當修改。html

盤古開天之ASCII編碼出現

最先的時候,是在學習C語言的時候接觸的ASCII編碼(American Standard Code for Information Interchange,美國信息交換標準代碼),知道是一種使用二進制(一個字節表示一個字符,8bit)來表示計算機的一些控制字符、通訊字符、大小寫英文字符、阿拉伯數字以及一些標點運算等符號。因爲是美國人制定的規則,當時只考慮了英語體系用到的一些符號(自私自利的美帝國主義,手動滑稽)。這種方案在當時計算機剛出現不久還能湊合使用,而且當時的存儲成本也比較高,使用一個字節來存儲也節省不少存儲資源,同時也提升了傳輸效率。因爲計算機技術發展迅猛,很快歐洲、中國、日本也開始開展本身的計算機研究。這時你們發現WTF,計算機不認識本身的母語呀,這怎麼能行,計算機也文化歧視?各個國家開始搞事情了。java

春秋戰國之各家編碼

首先發難的是歐美拉丁系國家,他們發現ASCII編碼只用了從0000 0000(二進制)到0111 1111(二進制)128種符號,浪費啊浪費。他們決定採用127號以後的空位來表示這些新的字母、符號,還加入了不少畫表格時須要用下到的橫線、豎線、交叉等形狀,一直把序號編到了最後一個狀態255。從128到255這一頁的字符集被稱"擴展字符集",也就是Latin-1字符集,即ISO-8859-1tomcat

這下歐美髮達國家是夠用了,可是老美沒想到第三世界的國家也須要使用計算機吧。勤勞智慧的中國人民說,「這都不是事兒」。咱們發揚"拿來主義"精神,取其精華,去其糟粕。把ASCII編碼的127位及以前的字符保留着,127位以後的那些亂七八糟的字符統統幹掉。而且規定:一個漢字使用兩個字節表示。,一個小於127的字符的意義與原來相同,但兩個大於127的字符連在一塊兒時,就表示一個漢字,前面的一個字節(他稱之爲高字節)從0xA1用到0xF7,後面一個字節(低字節)從0xA1到0xFE。一共收錄6763個漢字,其中一級漢字3755個,二級漢字3008個;同時收錄了包括拉丁字母、希臘字母、日文平假名及片假名字母、俄語西裏爾字母在內的682個字符。兩個字節長的就是"全角"字符,而原來在127號如下的那些就叫"半角"字符了。
這種字符方案叫作GB 2312字符集,已經將常見的使用頻率較高的一些漢字收錄進去,基本可以知足絕大多數中國人民使用啦。服務器

But,要知道中國文化博大精深,還有不少生僻字沒有辦法使用,萬一恰好是某個領導的名字呢(手動尷尬)。因而乾脆再也不要求低字節必定是127號以後的內碼,只要第一個字節是大於127就固定表示這是一個漢字的開始,無論後面跟的是否是擴展字符集裏的內容。結果擴展以後的編碼方案被稱爲 GBK 標準。GBK兼容了GB 2312的全部內容,同時又增長了近20000個新的漢字(包括繁體字)和符號。網絡

但還要團結少數民族呀,因而又提出了GB 18030,除保留所有GBK編碼漢字,在第二字節把能使用範圍再度進行擴展,增長了大約一百個漢字及四位元組編碼空間,將GBK做爲子集所有保留。架構

因爲這些漢字編碼標準都是採用兩個字節表示一個漢字,統稱爲"DBCS"(Double Byte Charecter Set 雙字節字符集)。所以開發人員在做中文處理的時候,常常要念一句咒語:"一個漢字算兩個英文字符!一個漢字算兩個英文字符……" 只有通過咒語加持的代碼才能正常運行。post

但是中國大陸用的是簡體字呀,雖然GBK已支持繁體字,當時臺灣、香港、澳門等繁體中文通行區的人民特立獨行,本身搞了一套Big5編碼。還有其餘國家的也各自爲政,韓文編碼EUC_KR字符集,日文編碼Shift_JIS字符集,俄文編碼KOI8-R字符集等等。書不一樣文,這簡直是阻礙人類文明在計算機世界的發展啊。學習

書同文之Unicode救世

爲告終束這種亂象,這時ISO(國際標準化組織)站出來了,他們絕對爲世界650種語言進行統一編碼。通過研究,終於整了一個Unicode字符集出來。因爲當時計算機的存儲器容量極大地發展了,空間不再成爲問題了。因而 ISO 就直接規定必須用兩個字節,也就是16位來統一表示全部的字符,對於ascii裏的那些「半角」字符,Unicode 包持其原編碼不變,只是將其長度由原來的8位擴展爲16位,而其餘文化和語言的字符則所有從新統一編碼。因爲"半角"英文符號只須要用到低8位,因此其高8位永遠是0,所以這種大氣的方案在保存英文文本時會多浪費一倍的空間。 並且原來的不少程序在計算字符串長度也不許確了,一箇中文和一個英文都是一個字符!此外,Unicode它只規定了符號的二進制代碼,卻沒有規定這個二進制代碼應該如何存儲,以及如何進行傳輸。因爲這些侷限,致使Unicode只能是一種理論上的標準。編碼

衆望所歸之UTF-8出世

隨着互聯網的興起,面向傳輸的衆多 UTF(Unicode Transformation Format)標準出現了,UTF-8 就是在互聯網上使用最廣的一種 Unicode 的實現方式。其餘實現方式還包括 UTF-16(字符用兩個字節或四個字節表示)和 UTF-32(字符用四個字節表示),不過在互聯網上基本不用。畫重點,這裏的關係是,UTF-8 是 Unicode 的實現方式之一。UTF-8 最大的一個特色,就是它是一種變長的編碼方式。它可使用1~4個字節表示一個符號,根據不一樣的符號而變化字節長度。UTF-8編碼規則:spa

  1. 對於單字節的符號,字節的第一位設爲0,後面7位爲這個符號的 Unicode 碼。所以對於英語字母,UTF-8 編碼和 ASCII 碼是相同的。

  2. 對於n字節的符號(n > 1),第一個字節的前n位都設爲1,第n + 1位設爲0,後面字節的前兩位一概設爲10。剩下的沒有說起的二進制位,所有爲這個符號的 Unicode 碼。

例如"漢"字的Unicode編碼是6C49。6C49在0800-FFFF之間,因此要用3字節模板:1110xxxx 10xxxxxx 10xxxxxx。將6C49寫成二進制是:0110 1100 0100 1001,再依序替代模板中x,獲得:1110-0110 10-110001 10-001001,即E6B189,這就是"漢"字的UTF-8編碼。

常見問題

Big endian與 Litter endian

使用UCS-2存儲Unicode編碼(也就是一個字符使用兩個字節存儲),因爲計算機架構的不一樣,好比,"漢"字,Unicode編碼16進制,使用Big endian(大頭方式)表示爲6C49,使用Litter endian(小頭方式)表示爲496C。那麼在網絡傳輸及本地文件存儲時,計算機怎麼知道使用何種方式呢?Unicode 規範定義,每個文件的最前面分別加入一個表示編碼順序的字符,這個字符的名字叫作"零寬度非換行空格"(zero width no-break space),若是一個文本文件的頭兩個字節是FE FF,就表示該文件採用大頭方式;若是頭兩個字節是FF FE,就表示該文件採用小頭方式。

有了UTF-8爲什麼還要使用GBK編碼

既然如今已經有了一個統一的UTF-8編碼來表示全部語言來,爲何如今不少程序以及系統仍舊還在使用GBK,Big5,ISO-8859-1等這些編碼呢?我以爲主要有兩點因素:

  1. 兼容問題。因爲以前的歷史緣由,致使不少系統及程序應用是使用其餘編碼來開發的,而UTF-8又不能兼容以前的編碼,若是要繼續使用也只能用對應的編碼方式。
  2. 資源問題。因爲UTF-8編碼是變長的,須要使用1~4個字節來表示一個字符,若是是漢字的話一般須要2~4個字節來表示。而使用GBK編碼只須要2個字節。當你的文本內容及使用的對象主要是中文環境時,使用GBK編碼將大大減小你的存儲空間、傳輸速度及網絡流量。

Java字符串編碼問題

對於Java以及tomcat遇到的一些編碼問題,可參考深刻分析Java中的中文編碼問題。該文章已經描述得十分透徹。在這裏就簡單說一下在Java編碼中遇到中午亂碼的幾個處理方式:

  1. 對請求參數進行編碼轉換

    String userName=request.getParamter("userName");
    userName=new String(userName.getByte("iso-8859-1"),"utf-8");

  2. 對請求頭進行編碼轉換

    request.setCharacterEncoding("UTF-8");//該方法只對POST方式提交的數據有效,對GET方式提交的數據無效!

  3. tomcat默認ISO-8859-1編碼,對tomcat服務器server.xml文件設置編碼,便可讓tomcat以UTF-8的編碼處理get請求。

    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>

參考資料

  1. 網頁編碼就是那點事
  2. ASCII 維基百科
  3. ISO/IEC 8859-1 維基百科
  4. GB 2312 維基百科
  5. GBK 維基百科
  6. 常見字符編碼
  7. ASCII,Unicode 和 UTF-8
  8. 深刻分析Java中的中文編碼問題
  9. 如何設置tomcat服務器編碼爲utf-8編碼
相關文章
相關標籤/搜索