java字符編碼


何為字符編碼(名詞):計算機中的任何信息它們都以0和1的方式存入計算機並得以處理,這些信息用哪些二進制數字來表示了,就需要一套規則,這套規則就是字符編碼(Character Code),比如,同樣一個字母'A',每種規范里面的表達存儲方式不一樣,ASCII是001,GB2312是002,沒以下都是它的規則,如:ASCII編碼表、GB2312編碼表、GBK編碼(即“國G標B”、“擴K展”前三個漢字的漢語拼音的第一個字母)、GB18030、Unicode編碼、UTF-8編碼等等(理解為一個國家或一個地區的語言包)

 

為什么需要知道字符編碼

在顯示器上看見的文字、圖片等信息在電腦里面其實並不是我們看見的樣子,即使 你知道所有信息都存儲在硬盤里,把它拆開也看不見里面有任何東西,只有些盤片。假設,你用顯微鏡把盤片放大,會看見盤片表面凹凸不平,凸起的地方被磁化,凹的地方是沒有被磁化;凸起的地方代表數字1,凹的地方代表數字0。 硬盤只能用0和1來表示所有文字、圖片等信息。那么字母”A”在硬盤上是如何存儲的呢?可能小張計算機存儲字母”A”是1100001,而小王存儲字母”A”是11000010,這樣雙方交換信息時就會誤解。比如小張把1100001發送給小王,小王並不認為1100001是字母”A”,可能認為這是 字母”X”,於是小王在用記事本訪問存儲在硬盤上的1100001時,在屏幕上 顯示的就是字母”X”。也就是說,小張和小王使用了不同的編碼表。小張用的編碼表是ASCII,ASCII編碼表把26個字母都一一的對應到2進制1和0 上;小王用的編碼表可能是EBCDIC,只不過EBCDIC編碼與ASCII編碼中的字母和01的對應關系不同。一般地說,開放的操作系統(LINUX 、WINDOWS等)采用ASCII 編碼,而大型主機系統(MVS 、OS/390等)采用EBCDIC 編碼。在發送數據給對方前,需要事先告知對方自己所使用的編碼,或者通過轉碼,使不同編碼方案的兩個系統可溝通自如。(其實發過來的都是0101010。。。,對方告知所使用的編碼規范(假如是ASCII編碼),就使用ASCII編碼表找到對應所表達的字符,再將字符通過EBCDIC編碼表找到對應的編碼,然后才能得到本機正常情況下的字符)

這就解釋了亂碼的原因:010101在你那里代表正常的字符,你那邊編碼規范是ASCII編碼,到我這邊來編碼規范是GB2312,編碼表變了,010101代表什么西方字符或者問號等等,於是亂碼文件就產生了

 

解碼:你用文件編輯軟件打開某個文件,假設里面裝的010101,比如以UTF-8打開,就以UTF-8的語言包去解碼010101,它代表劉德華,比如以GBK解碼的語言包去解碼010101,它代表梁朝偉

編碼:名詞即語言包,動詞的話,就是UTF-8用010101編碼(表示)劉德華,GBK以101010編碼(表示)劉德華 

轉碼:比如你之前使用GBK(2、3、4)打開的,現在我需要用UTF-8(5、6、7)打開

public static void convertionString() throws UnsupportedEncodingException{  
        String s = "任何信息";  //計算機上的任何信息是以010101存在的           1   
        byte[] b = s.getBytes("gbk");//得到文件以GBK編碼表存在的方式(字節)    2
        String sa = new String(b, "gbk");//用GBK編碼表去解碼字節代表什么     3
        System.out.println(sa + b.length + "\n");  //GBK編碼下的結果      4
        b = sa.getBytes("utf-8");////得到文件以utf-8編碼表存在的方式(字節)    5
        sa = new String(b, "utf-8");//用utf-8編碼表去解碼字節代表什么        6
        System.err.println(sa + b.length);  //utf-8編碼下的結果           7
    } 

 

字符編碼的發展

第一階段:ASCII階段,(American Standard Code for Information Interchange, "美國信息交換標准碼")

計算機當時只支持英語,字符在計算機中都是以0和1的方式存儲的。象a、b、c、d這樣的52個字母(包括大寫)、以及0、1、 2等數字還有一些常用的符號(例如*、#、@等)在計算機中存儲時也要使用二進制數來表示,而具體用哪些二進制數字表示哪個符號,就必須要有一定的規則, 於是美國有關的標准化組織就出台了所謂的ASCII編碼,統一規定了上述常用符號用哪個二進制數來表示。ASCII碼規定每個字符例如 “a”使用1個字節來表示,也就是8位的二進制組合,那么就有00000000-11111111一共256種組合,也就是可以表示256個不同的字符。

其中0-31:是控制字符或通訊專用字符(不可以顯示的字符,其余為可顯示字符),如控制符:LF(換行)、CR(回車)等。

32-126:是字符,其中32是空格,48-57為0-9的阿拉伯數字,65-90為26個大寫英文字母,97-122為26個小寫英文字母,其余的是一些標點符號,運算符號等。

ASSCII共計有128個,從0到127,也就是從00000000-01111111,最高位都是0。

ISO 8859-1它以ASCII為基礎,在空置的0xA0-0xFF的范圍內,加入96個字母及符號,藉以供使用變音符號的拉丁字母語言使用。

 

第二階段:ANSI編碼階段(American National Standards Institute,美國國家標准學會的標准碼)

ASCII只能表示英文字符,那么其他字符怎么表示呢?漢語是這樣解決的,用兩個ASCII表示一個漢字, 而且不用前面的128個,為什么不用已經在上一篇中介紹了,因為前128個是人家的英文。不能占啊,否則就混亂了。比如漢字“中”在中文操作系統中使用 [0xD6,0xD0] 這兩個字節存儲,為什么呢,這里簡單解釋一下,“中”的區位碼是 54 48 ,那么“中”的,國標碼就是54 48的十六進制+上2020H=5650H,那么“中”的機內碼就是=“中的國標碼+8080H=D6D0H(這都是上一篇的內容,不明白的可以看上一 篇),這樣每個漢字也都有了自己的編碼,漢字編碼解決了,這就是中國的GB2312編碼標准,但是這是中國漢字的編碼,那么其他國家呢?其他的國家的計算 機操作系統中可能把[0xD6,0xD0] 這兩個字節存儲成他們的文字,而不是“中”,不同的國家和地區制定了不同的標准,這些使用 2 個字節來代表一個字符的各種文字延伸編碼方式,稱為 ANSI 編碼

在簡體中文系統下,ANSI 編碼代表 GB2312 編碼,在日文操作系統下,ANSI 編碼代表 JIS 編碼。不同 ANSI 編碼之間互不兼容,當信息在國際間交流時,無法將屬於兩種語言的文字,存儲在同一段 ANSI 編碼的文本中。

 

第三階段:Unicode(16進制) 字符集編碼階段(Universal Multiple-Octet Coded Character Set, 通用多八位編碼字符集的簡稱)

為了使國際間信息交流更加方便,國際組織制定了 UNICODE(16進制) 字符集, 為各種語言中的每一個字符設定了統一並且唯一的數字編號,以滿足跨語言、跨平台進行文本轉換、處理的要求。Unicode固然統一了編碼方式,但是它的效率不高,比如UCS-4(Unicode的標准之一)規定用4個字節存儲一個符號,那么每個英文字母前都必然有三個字節是0,這對存儲和傳輸來說都很耗資源

UCS只是規定如何編碼,並沒有規定如何傳輸、保存這個編碼。

UTF-8:utf(Unicode Translation Format)為了提高Unicode的編碼效率,於是就出現了UTF-8編碼。Unicode規定世界上每個字符對應的編碼號,utf-8定義了如何存儲字符,UTF-8使用可變長度字節來儲存 Unicode字符,例如ASCII字母繼續使用1字節儲存,重音文字、希臘字母或西里爾字母等使用2字節來儲存,而常用的漢字就要使用3字節。輔助平面字符則使用4字節

UTF-16、UTF-32 都是將數字轉換到程序數據的編碼方案。

 

java在內存中運算是使用的雙字節字符unicode的編碼方式

內存中對字符串操作其實不用考慮字符集。
只有在讀取到內存中,和輸出時,需要考慮字符集轉換。

http://www.blogjava.net/liuyz2006/articles/385768.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM