1. 程式人生 > >Java字元編碼詳解

Java字元編碼詳解

char

  1. “位元組”是byte,“位”是bit ;
  2. 1 byte = 8 bit ;
  3. char 在Java中是2個位元組。java採用unicode(《java核心技術卷一》裡面有詳細說明),2個位元組(16位)來表示一個字元。而Unicode編碼包括漢字,所以也可以給char賦值漢字。

那麼我們在程式中的char =‘\123’和char = ‘\u0023’甚至’\”’這些又是怎麼回事呢?

這個需要從計算機的歷史說起。

Ascii及中國的編碼

既然是程式設計師,那麼大家對Ascii肯定有一定的瞭解。
Ascii(American Standard Code for Information Interchange),美國資訊互換標準程式碼,官方的ASCII碼錶如下->

AsciiTABLE

Ascii為八位一個位元組,一共可以組合出256(2的8次方)種不同的狀態。

一開始美國人把其中的編號從0開始的32種狀態分別規定了特殊的用途,一但終端、印表機遇上約定好的這些位元組被傳過來時,就要做一些約定的動作。遇上00x10, 終端就換行,例好遇上0x1b, 印表機就列印反白的字,或者終端就用彩色顯示字母。
這些0x20以下的位元組狀態稱為”控制碼”。

接著把所有的空格、標點符號、數字、大小寫字母分別用連續的位元組狀態表示,一直編到了第127號,這樣計算機就可以用不同位元組來儲存英語的文字了。

後來,就像建造巴比倫塔一樣,世界各地的都開始使用計算機,但是很多國家用的不是英文,他們的字母裡有許多是ASCII裡沒有的。他們決定採用127號之後的空位來表示這些新的字母、符號,還加入了很多畫表格時需要用下到的橫線、豎線、交叉等形狀,一直把序號編到了最後一個狀態255。
從128到255這一頁的字符集被稱”擴充套件字符集”。

等到我們天朝用計算機時發現挖槽你他媽一個位置都沒留給我,我還有幾千上萬個文字要儲存呢,於是我們自己創造了兩個位元組編碼的“GB2312”以及之後的同樣是兩個位元組的“GBK”。之後“GBK”擴充套件為“GB18030”,這些編碼標準被通稱為 “DBCS”(Double Byte Charecter Set 雙位元組字符集)。

DBSC系列的標準的最大特點是,最大的特點是兩位元組長的漢字字元和一位元組長的英文字元並存於同一套編碼方案裡,如果一個位元組小於127那麼按照Ascii的編碼,如果大於127那麼其和後面的字元組成一個漢字字元。

然後各國也是按照自己的需求弄了一套自己可用的編碼。很愉快大家都能用了,接著發現不對啊,各個國家之間電腦需要交流,你的資源到我這裡程式設計亂碼,我的資源你也用不了。

於是。。一個叫 ISO (國際標誰化組織)的國際組織決定著手解決這個問題。他們採用的方法很簡單:廢了所有的地區性編碼方案,重新搞一個包括了地球上所有文化、所有字母和符號的編碼!他們打算叫它”Universal Multiple-Octet Coded Character Set”,簡稱 UCS, 俗稱 “UNICODE”。
Unicode的字元編碼表:來自維基百科的Unicode編碼表

對於ascii裡的那些“半形”字元(即前面排到128個字元),UNICODE 包持其原編碼不變,只是將其長度由原來的8位擴充套件為16位,而其他文化和語言的字元則全部重新統一編碼。由於”半形”英文符號只需要用到低8位,所以其高8位永遠是0,因此這種大氣的方案在儲存英文文字時會多浪費一倍的空間。

Unicode及UTF

UNICODE 是用兩個位元組來表示為一個字元,他總共可以組合出65535不同的字元,這大概已經可以覆蓋世界上所有文化的符號。UNICODE 如何在網路上傳輸也是一個必須考慮的問題,於是面向傳輸的眾多 UTF(UCS Transfer Format)標準出現了,顧名思義,UTF8就是每次8個位傳輸資料,而UTF16就是每次16個位,只不過為了傳輸時的可靠性,從UNICODE到UTF時並不是直接的對應,而是要過一些演算法和規則來轉換。而且網路傳輸字元編碼也涉及到大端小端的問題。

java中的編碼

前面說了,java使用到編碼是UNICODE。怎麼具體“體會到”這種編碼呢?我們可以用java中的轉義符 \。

  • 一、我們直接使用“\”來轉化數字為字元的話,後面的數字應為八進位制
    而且只能轉化一個位元組大小,即255個字元,如下:
    八進位制轉義序列:\ + 八進位制數;範圍’\000’~’\377’(對應十進位制0~255)
    \0:空字元
    有人問了Unicode不是兩個位元組嗎,為什麼這裡一個位元組就可以,其實java在這裡會把它轉化為兩個位元組按Unicode轉換。記住是Unicode,不要因為一個位元組就以為是ASCII編碼,如下程式碼:
   System.out.println('\367'); //這裡輸出的是 ÷
   //八進位制367轉化為10進製為247
   System.out.println((int) '÷');//輸出十進位制:247
   //序號247在Ascii和Unicode對應的字元如下:

Ascii:這裡寫圖片描述

Unicode:這裡寫圖片描述

  • 二、 Unicode轉義字元:\u + 4個十六進位制數字;對應十進位制範圍是0~65535
    \u0000:空字元
    //八進位制367對應十六進位制00F7,所以下面兩個輸出都是 ÷
   System.out.println('\367');
   System.out.println('\u00F7');
   System.out.println('\u0000~uFFFF'); //我們電腦出現的每個漢字都包含在這其中
  • 三、 特殊字元:就3個
    因為在Java中 雙引號”、引號’、反斜杆\ 都有特定的含義,雙引號要包住字串,引號要包住字元,反斜槓是轉義符,所以我們通過在加一個轉義符\讓他們真正代表他們自己。
    \”:雙引號
    \’:單引號
    \:反斜線
   String fieldsNmae = "呵呵";
   System.out.println("fieldsName:\"" + fieldsNmae + "\"");
   //不復雜,你就把\"當成字元,輸出:fieldsName:"呵呵"
  • 四.控制字元:5個
    轉義符\加固定字元在java中有五個,表示一定的控制操作
    \r 回車
    \n 換行
    \f 走紙換頁
    \t 橫向跳格
    \b 退格
System.out.println("開心\n就好");
//輸出:
開心
就好

最後要注意,Java是平臺無關的,儲存預設是大端。而機器用大端還是小端是處理器決定的,跟系統沒有關係。

中文的半形和全形

在DBCS系列的編碼裡面,把連在 ASCII 裡本來就有的數字、標點、字母都統統重新編了兩個位元組長的編碼,這就是常說的”全形”字元,而原來在127號以下的那些就叫”半形”字元了。所以如果這些例如字母使用一個位元組編碼就是“半形”,兩個位元組就是“全形”。其實樣子看起來還是有區別的:

半形:abcdefghi
全形:abcdefghi
   博主是最帥的程式設計師
   //可以看出全形字母和中文一樣都是佔用這相同的空間大小

(unicode裡面對這些全形字元也有對應的編碼)