一、字符編碼的發展歷程java
①、ASCII 碼數組
由於計算機只認識數字,因此咱們在計算機裏面的一切數據都是以數字來表示,由於英文字符有限,因此規定使用的字節的最高位是 0,每個字節都是以 0-127 之間的數字來表示。好比 A 對應 65,a 對應 97。這即是 美國標準信息交換碼,ASCII服務器
String str = new String("Aa"); byte[] strASCII = str.getBytes("ASCII"); System.out.println(Arrays.toString(strASCII));//[65, 97]
②、GB2312 碼網絡
隨着計算機在全球的普及,不少國家和地區都把本身的字符引入了計算機,好比漢字。此時發現一個字節能表示的數字範圍過小,不能包含全部的中文漢字。那麼就規定使用兩個字節來表示一個漢字。編碼
規定:原有的 ASCII 字符的編碼保持不變,仍然使用一個字節表示,爲了區別一箇中文字符與兩個 ASCII 碼字符相區別。中文字符的每一個字節最高位規定爲 1(即中文的二進制是負數),這即是 GB2312 編碼計算機網絡
String str = new String("Aa帥鍋"); byte[] strASCII = str.getBytes("GB2312"); System.out.println(Arrays.toString(strASCII));//[65, 97, -53, -89, -71, -8]
③、GBKcode
因爲中國漢字太多,在 GB2312 的基礎上增長了更多的中文字符,這種編碼是 GBKblog
問題:若是隻是在中國,那麼你們都認識漢字,可是若是是別的國家,而該國家的碼錶中是沒有收錄漢字的。那麼計算機在顯示的時候就爲亂碼或是別的字符字符串
解決辦法:爲了解決各個國家由於本地化字符編碼帶來的影響,就把全世界全部的字符統一進行編碼---Unicode 編碼get
此時某一個字符在全世界任何地方顯示都是固定的,好比漢字 哥,在任何地方都是以十六進制 54E5 來表示。
Unicode 的字符編碼都佔有兩個字節
④、UTF-8
是一種針對 Unicode 的可變長度字符編碼,又稱爲 萬國碼,是 Unicode 的實現方式之一。編碼中的第一個字節仍與 ASCII 兼容,這使得原來處理 ASCII 字符的軟件無須或只需作少部分修改,便可繼續使用。所以,它逐漸成爲電子郵件、網頁及其餘存儲或傳送文字的應用中,優先採用的編碼。互聯網工程工做小組(IETF)要求全部互聯網協議都必須支持 UTF-8 編碼
String str = new String("Aa帥鍋"); byte[] strASCII = str.getBytes("UTF-8"); System.out.println(Arrays.toString(strASCII));//[65, 97, -27, -72, -123, -23, -108, -123]
存儲字母、數字:不管什麼字符集都佔有 1 個字節
存儲漢字:GBK 家族佔有 2 個字節。UTF-8 佔有 3 個字節
不能使用單字節的字符集(ASCII/ISO-8859-1)來存儲中文
二、字符的編碼和解碼
信息在計算機網絡中傳輸是以字節的形式。那麼如何變爲字節?這就是編碼的過程。那麼計算機接收了這個編碼,如何讓使用者認識呢?那必需要將字節轉換爲人所識別的字符串形式,這就是解碼的過程。
編碼:將字符串轉換爲 byte 數組
解碼:把 byte 數組轉換爲 字符串
注意:①、編碼格式和解碼格式必須一致,不然亂碼
String str = new String("Aa帥鍋"); //編碼操做 byte[] strByte = str.getBytes("GBK"); System.out.println(Arrays.toString(strByte));//[65, 97, -53, -89, -71, -8] //解碼操做 //注意編碼的字符集和解碼的字符集格式必須一致(是其擴展字符集也能夠),不然會亂碼 //第一種:編碼格式爲 GBK,解碼格式爲 ISO-8859-1 那麼就會亂碼 String str2 = new String(strByte,"ISO-8859-1"); System.out.println(str2); //Aa?§?? //第二種:編碼和解碼格式一致 String str3 = new String(strByte,"GBK"); System.out.println(str3); //Aa帥鍋
②、有時候編碼爲和解碼格式一致了,可是仍是亂碼,這是由於在數據在傳輸過程當中通過服務器的處理,而這個服務器多是外國人編寫的,那麼就會將數據轉換爲 別的字符格式,那麼你若是仍是直接轉爲本身想要的格式是會亂碼的。
解決辦法:先獲取通過服務器以後的數據還原編碼,而後在進行解碼
String str = new String("Aa帥鍋"); //編碼操做 byte[] strByte = str.getBytes("UTF-8"); System.out.println(Arrays.toString(strByte));//[65, 97, -27, -72, -123, -23, -108, -123] //中間通過了服務器的傳輸,編碼格式轉成了 ISO-8859-1 String str2 = new String(strByte,"ISO-8859-1"); //解碼操做 ,此時若是直接進行解碼,那麼會亂碼 String str3 = new String(str2.getBytes(),"UTF-8"); System.out.println(str3); //Aa??????? //對於上面的亂碼,咱們必須先還原服務器以前的編碼格式,而後在進行解碼。那麼就不會亂碼 byte[] strByte2 = str2.getBytes("ISO-8859-1"); String str4 = new String(strByte2,"UTF-8"); System.out.println(str4); //Aa帥鍋