理清計算機漢字編碼問題(上)

1. 常見編碼

1.1 ASCII

  ASCII(American Standard Code for Information Interchange:美國信息交換標準代碼)是基於拉丁字母的一套電腦編碼系統,主要用於顯示現代英語和其他西歐語言。它是現今最通用的信息交換標準,並等同於國際標準ISO/IEC 646。
  ASCII碼錶分爲兩部分:控制字符和可顯示字符。這個不用多解釋,相信學過C語言或者計算機電子信息相關專業的都涉及,更多請參考ASCII碼對照表

1.2 漢字機內碼

  漢字機內碼,又稱“漢字ASCII碼”,簡稱“內碼”,指計算機內部存儲,處理加工和傳輸漢字時所用的由0和1符號組成的代碼。輸入碼被接受後就由漢字操作系統的“輸入碼轉換模塊”轉換爲機內碼,與所採用的鍵盤輸入法無關。機內碼是漢字最基本的編碼,不管是什麼漢字系統和漢字輸入方法,輸入的漢字外碼到機器內部都要轉換成機內碼,才能被存儲和進行各種處理。
關於國標碼、區位碼和機內碼之間的換算,參考

  1. CSDN ~ https://blog.csdn.net/sxhelijian/article/details/24498045
  2. 博客園 ~ https://www.cnblogs.com/hrhguanli/p/3805799.html

C語言獲取漢字機內碼、區位碼、國際碼:

#include<stdio.h>
void main(void) {
	unsigned char temp[2];
	scanf("%s",temp);
	printf("機內碼高字節是0x%.2x\n",temp[0]);
	printf("機內碼低字節是0x%.2x\n",temp[1]);
	printf("區位碼區碼是%2d\n",temp[0]-0xa0);
	printf("區位碼位碼是%2d\n",temp[1]-0xa0);
	printf("國際碼高字節是0x%.2x\n",temp[0]-0x80);
	printf("國際碼低字節是0x%.2x\n",temp[1]-0x80);
}

1.3 Unicode

  Unicode(統一碼、萬國碼、單一碼)是計算機科學領域裏的一項業界標準,包括字符集、編碼方案等。Unicode 是爲了解決傳統的字符編碼方案的侷限而產生的,它爲每種語言中的每個字符設定了統一併且唯一的二進制編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。1990年開始研發,1994年正式公佈。
  Unicode只有一個字符集,中、日、韓的三種文字佔用了Unicode中0x3000到0x9FFF的部分 Unicode目前普遍採用的是UCS-2,它用兩個字節來編碼一個字符, 比如漢字"經"的編碼是0x7ECF,注意字符碼一般用十六進制來 表示,爲了與十進制區分,十六進制以0x開頭,0x7ECF轉換成十進制 就是32463,UCS-2用兩個字節來編碼字符,兩個字節就是16位二進制, 2的16次方等於65536,所以UCS-2最多能編碼65536個字符。 編碼從0到127的字符與ASCII編碼的字符一樣,比如字母"a"的Unicode 編碼是0x0061,十進制是97,而"a"的ASCII編碼是0x61,十進制也是97, 對於漢字的編碼,事實上Unicode對漢字支持不怎麼好,這也是沒辦法的, 簡體和繁體總共有六七萬個漢字,而UCS-2最多能表示65536個,才六萬 多個,所以Unicode只能排除一些幾乎不用的漢字,好在常用的簡體漢字 也不過七千多個,爲了能表示所有漢字,Unicode也有UCS-4規範,就是用 4個字節來編碼字符。
更多請參考 ~ Unicode字符表

1.4 UTF-8

  互聯網的普及,強烈要求出現一種統一的編碼方式。UTF-8 就是在互聯網上使用最廣的一種 Unicode 的實現方式。其他實現方式還包括 UTF-16(字符用兩個字節或四個字節表示)和 UTF-32(字符用四個字節表示),不過在互聯網上基本不用。重複一遍,這裏的關係是,UTF-8 是 Unicode 的實現方式之一
  UTF-8 最大的一個特點,就是它是一種變長的編碼方式。它可以使用1~4個字節表示一個符號,根據不同的符號而變化字節長度。

UTF-8 的編碼規則很簡單,只有二條:

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

下表總結了編碼規則,字母x表示可用編碼的位。

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

  跟據上表,解讀 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。

1.5 GBK、GB2312

  GBK漢字國標擴展碼,基本上採用了原來GB2312-80所有的漢字及碼位,並涵蓋了原Unicode中所有的漢字20902。GBK編碼是中國大陸制訂的、等同於UCS的新的中文編碼擴展國家標準。
  GB 2312或GB 2312-80是一個簡體中文字符集的中國國家標準,GB 2312標準共收錄6763個漢字。

1.6 GBK/GB2312、UTF-8、Unicode區別和聯繫

想要進一步弄清楚,GBK/GB2312、UTF-8和Unicode間的區別與聯繫,請仔細閱讀下面這6篇不錯的文章。

  1. 字符編碼筆記:ASCII,Unicode 和 UTF-8
  2. ASCII,Unicode和UTF-8終於找到一個能完全搞清楚的文章了
  3. UTF-8 GBK UTF8 GB2312之間的區別和關係
  4. 編碼之------Unicode到底是什麼?神馬utf-8和gbk到底是什麼?utf-8和Unicode關係?
  5. 字符編碼GB2312、GBK、UTF-8的區別
  6. 區分: 編碼方式 字符集 Unicode UTF-8

2. OS中通用的字符編碼工作方式

工作方式

  1. 在計算機內存中,統一使用Unicode編碼,當需要保存到硬盤或者需要傳輸的時候,就轉換爲UTF-8編碼;
  2. 用記事本編輯的時候,從文件讀取的UTF-8字符被轉換爲Unicode字符到內存裏,編輯完成後,保存的時候再把Unicode轉換爲UTF-8保存到文件;
  3. 瀏覽網頁的時候,服務器會把動態生成的Unicode內容轉換爲UTF-8再傳輸到瀏覽器。

3. 總結

計算機中文編碼
  在操作系統(Windows、安卓)中,字符編碼工作方式參照上文【字符編碼工作方式】。但在MCU微機中,處理方式不一樣,在微機中由於資源有限,通常是通過漢字機內碼計算漢字字符對應的地址,然後查詢字庫IC(帶rom或者flash)顯示。上圖中,漢字在計算機內存儲、處理/傳輸都是機內碼,但爲了信息交換於是便產生了國標(GBK/GB2312)即《信息交換用漢字編碼字符集》,國標當然只適用於國內,於是國際上便產生了Unicode萬國碼,它又僅僅定義了一個字符集,UTF-8則就是按照Unicode字符實現的一種編碼
  剛開始就很想弄懂Unicode、GBK/GB2312、UTF-8和機內碼,徹底分清它們,但是查詢了之後很多概念容易一頭霧水。透過上圖,大家應該很容易,理清它們間的關係和區別,相信在開發中遇到漢字編碼都會迎刃而解,嘻嘻!
附:

  1. UTF-8轉Unicode ~ http://tool.oschina.net/encode?type=2
  2. 漢字字符集編碼查詢 ~ https://www.qqxiuzi.cn/bianma/zifuji.php
  3. 16進制到文本字符串的轉換,在線實時轉換 ~ http://www.bejson.com/convert/ox2str/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章