说明: 在JVM内部,字符串在java中统一用unicode表示。无论源文件是用什么编码,都会先用相应地编码方式解析成字符串,再将字符串转换为unicode格式的字节数组,作为内部存储。因此,不论源码文件是什么格式,同样的字符串,最后得到的unicode字节数组是完全一致的。
在程序未运行时,字符串以原始编码的字节数组存储在系统磁盘中;在程序运行时,字符串会被转化为unicode字符数组存储在JVM内存中(原始字节数组-->原始编码方式解码-->字符串-->Unicode编码-->Unicode字节数组)
其他:
1、ASII码:字符串中的每个字符用一个字节表示。每个字符实际上只使用了7位,从00h-7Fh。只能表达128个字符。不能代表汉字。
2、Unicode码:字符串中的每个字符用两个字节表示。
编码:字符串--->字节数组
解码:字节数组--->字符串
字符串GBK转UTF-8过程:
1、字符串-->经过GBK编码-->GBK字节数组 (若直接使用UTF8解码GBK字节数组,将会乱码) 2、GBK字节数组-->经过GBK解码-->得到字符串-->使用unicode编码-->unicode字节数组 (将GBK字节数组转化为Unicode字节数组) 3、unicode字节数组-->使用unicode解码-->得到字符串-->使用UTF8编码-->UTF8字节数组 (再将unicode字节数组转化为UTF8字节数组) 4、UTF8字节数组-->使用UTF8解码-->得到字符串 (解码UTF8字节数组)
测试:
public class TestExcode { public static void main(String[] args) throws IOException { testStrEncode1(); //testStrEncode2(); //testStrEncode3(); } public static void testStrEncode1() throws UnsupportedEncodingException { String a = "你好"; //程序未运行时,原始编码为UTF-8,底层存储是UTF-8编码后的字节数组,我们看到的信息是通过UTF-8解码之后显示的。 //程序运行时,a被转化为unicode字节数组存储在JVM内存中 //使用ISO-8859-1编码时,会先将unicode字节数组解码得到字符串,再用ISO-8859-1编码字符串得到字节数组 byte[] b = a.getBytes("ISO-8859-1"); //ISO-8859-1无法编码中文,新的字节数组已经不同于原始字节数组 byte[] c = a.getBytes("UTF-8"); //解码和编码均为UTF-8,新的字节数组和原始字节数组仍然相同 //使用UTF-8解码刚才ISO-8859-1编码的字节数组 //解码得到的字符串与原始字符串不同(乱码) String result = new String(b,"UTF-8"); String result1 = new String(c,"UTF-8"); System.out.println(result); //输出'??' ,因为ISO-8859-1无法编码中文 System.out.println(result1); //输出'你好' } public static void testStrEncode2() throws UnsupportedEncodingException { String a = "ä½ å¥½"; //原始编码为UTF-8,底层存储是UTF-8编码后的字节数组,我们看到的信息是UTF-8解码之后显示的。 //程序运行时,a被转化为unicode字节数组存储在JVM内存中 //使用ISO-8859-1编码时,会先将unicode字节数组解码得到字符串,再用ISO-8859-1编码字符串得到新的字节数组 byte[] b = a.getBytes("ISO-8859-1"); //ISO-8859-1编码可以编码"ä½ å¥½",但新的字节数组和原始字节数组已经不同了 byte[] c = a.getBytes("UTF-8"); //UTF-8可以编码"ä½ å¥½",新的字节数组和原始字节数组仍然相同 //使用UTF-8解码刚才ISO-8859-1编码的字节数组 //解码得到的字符串与原始字符串不同 String result = new String(b,"UTF-8"); String result1 = new String(c,"ISO-8859-1"); System.out.println(result); //输出'你好' System.out.println(result1); //输出'ä½ å¥½' //分析:对比testStrEncode1和testStrEncode2 //将"你好"替换为"ä½ å¥½"后,result输出'你好',result1输出"ä½ å¥½", //这表示"ä½ å¥½"用ISO-8859-1编码后的字节数组和"你好"用UTF-8编码后的字节数组相同 }public static void testStrEncode3() throws UnsupportedEncodingException { //GBK、ISO-8859-1、UTF-8、Unicode等编码方式之间不存在包含关系 //GBK和UTF-8都支持中文和英文,但是UTF-8不仅支持中文,还支持其他国家的语言,应用更广泛 String fileName = "我最亲爱的祖国"; //GBK编码,GBK解码。正常输出。 System.out.println(new String(fileName.getBytes("GBK"),"GBK")); //GBK编码,ISO-8859-1解码。乱码 System.out.println(new String(fileName.getBytes("GBK"),"ISO-8859-1")); //GBK编码,使用默认UTF-8解码。乱码 System.out.println(new String(fileName.getBytes("GBK"))); //ISO-8859-1编码,ISO-8859-1解码。ISO-8859-1编码不了中文,编码失败,会乱码。 System.out.println(new String(fileName.getBytes("ISO-8859-1"),"ISO-8859-1")); //ISO-8859-1编码,使用默认UTF-8解码。乱码 System.out.println(new String(fileName.getBytes("ISO-8859-1"))); //ISO-8859-1编码,GBK解码。乱码 System.out.println(new String(fileName.getBytes("ISO-8859-1"),"GBK")); //UTF-8编码,使用默认UTF-8解码。正常输出 System.out.println(new String(fileName.getBytes("UTF-8"))); //UTF-8编码,ISO-8859-1解码。乱码 System.out.println(new String(fileName.getBytes("UTF-8"),"ISO-8859-1")); //UTF-8编码,GBK解码。乱码 System.out.println(new String(fileName.getBytes("UTF-8"),"GBK")); } }