new String()傳入字節數組生成String後,通過getBytes()得到的結果和原來不同

     發現一個神奇的問題。

    

package com.ggp.sqy42d;

import java.util.Arrays;

/**
 * @author: ggp
 * @Date: 2019/3/22 14:30
 * @Description:
 */
public class test {
    public static void main(String[] args) {
        byte[] bytes = new byte[]{-66,-98,-22,-68,-99};
        String str = new String(bytes);
        System.out.println(Arrays.toString(str.getBytes()));
    }
}

結果

D:\tool\jdk6\jdk1.6.0_45\bin\java.exe "-javaagent:D:\tool\IntelliJ IDEA 2018.3.3\lib\idea_rt.jar=53493:D:\tool\IntelliJ IDEA 2018.3.3\bin" -Dfile.encoding=UTF-8 -classpath D:\tool\jdk6\jdk1.6.0_45\jre\lib\charsets.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\deploy.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\ext\dnsns.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\ext\localedata.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\ext\sunjce_provider.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\ext\sunmscapi.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\ext\sunpkcs11.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\javaws.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\jce.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\jsse.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\management-agent.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\plugin.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\resources.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\rt.jar;D:\project\Util\out\production\Util;C:\Users\admin\Downloads\bcprov-jdk15on-1.59.jar;C:\Users\admin\Downloads\commons-lang3-3.1.jar com.ggp.sqy42d.test
[-17, -65, -67, -17, -65, -67, -22, -68, -99]

Process finished with exit code 0

爲什麼出現這種情況呢?

首先我們並沒有指定new String()的字符集和getBytes()的字符集

它就會使用環境的默認的字符集,一般是utf-8,我們需要了解一下各種編碼

到編碼,得先從ASCII編碼講起。ASCII編碼是由美國人發明,美國的字符不超過255個,所以ASCII編碼使用了8bit 即一個字節來存儲字符。由於漢字的數量遠超255個,所以中國自己發明了一個GB2312編碼來表示漢字,一般的漢字使用2個字節,對於一些生僻的漢字則使用更多的字節來表示,當然,GB2313編碼是可以兼容ASCII碼的。

        然後,日本,韓國等等國家也自己發明了一套編碼方法,這時候又出現了一個新的問題。如果一篇文章裏面,即有中文,又有日文的話,無論使用中文的編碼方法還是使用日文的編碼方法都會出現亂碼。隨後,unicode編碼便應運而生。unicode編碼對文字的編碼進行了統一,當然,unicode只是一種編碼規範,它有多個版本,常用的unicode編碼使用了16位來存儲字符,16位的存儲空間足以容納世界上所有書面字符(對於漢字來說,一共有6萬多個,只能包含其中的一些常用漢字,所以unicode編碼對於漢字的兼容性並不是特別好)。unicode編碼兼容了ASCII碼,ASCII碼轉unicode編碼時,保持後8位不變,前8位只需要用0去補全即可。

        使用了unicode編碼後,又有新的問題出現。因爲unicode編碼是用兩個字節來存儲字符,如果一篇文章中,大部分都是英文,使用unicode編碼就會造成空間的浪費,對英文部分使用ASCII碼只需要一個字節就可以了。這時候,utf-8解決了這個問題。utf-8是一種可變長的字符編碼,當存儲英文時只使用一個字節,節省了一半的空間,而存儲中文字符時,長度還是不變。utf-8雖然壓縮了存儲空間,但是如果在內存中存儲,使用utf-8卻由於它的長度不固定,帶來了很大的不便,使得在內存處理字符變得複雜。應對這個問題的解決策略是:在內存中存儲字符時還是使用unicode編碼,因爲unicode編碼的長度固定,處理起來很方便。而在文件的存儲中,則使用utf-8編碼,可以壓縮內存,節省空間。這裏一般有個自動轉換的機制,即從文件中讀取utf-8編碼到內存時,會自動轉換爲unicode編碼,而從內存中將字符保存到文件時,則自動轉換爲utf-8編碼。

    這樣一來,我們的問題就浮現了,我們的字節數組,轉爲utf-8字符串後,內部的字節已經發生了變化,所以我們應該指定編碼,比如我們指定ISO-8859-1,結果如下

package com.ggp.sqy42d;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

/**
 * @author: ggp
 * @Date: 2019/3/22 14:30
 * @Description:
 */
public class test {
    public static void main(String[] args) {
        byte[] bytes = new byte[]{-66,-98,-22,-68,-99};
        String str = null;
        try {
            str = new String(bytes,0,bytes.length,"ISO-8859-1");
            System.out.println(Arrays.toString(str.getBytes("ISO-8859-1")));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

    }
}

結果

D:\tool\jdk6\jdk1.6.0_45\bin\java.exe "-javaagent:D:\tool\IntelliJ IDEA 2018.3.3\lib\idea_rt.jar=55947:D:\tool\IntelliJ IDEA 2018.3.3\bin" -Dfile.encoding=UTF-8 -classpath D:\tool\jdk6\jdk1.6.0_45\jre\lib\charsets.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\deploy.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\ext\dnsns.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\ext\localedata.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\ext\sunjce_provider.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\ext\sunmscapi.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\ext\sunpkcs11.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\javaws.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\jce.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\jsse.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\management-agent.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\plugin.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\resources.jar;D:\tool\jdk6\jdk1.6.0_45\jre\lib\rt.jar;D:\project\Util\out\production\Util;C:\Users\admin\Downloads\bcprov-jdk15on-1.59.jar;C:\Users\admin\Downloads\commons-lang3-3.1.jar com.ggp.sqy42d.test
[-66, -98, -22, -68, -99]

Process finished with exit code 0

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章