先看下面这段代码的运行结果
String str = "中国"; System.out.println("第一部分-------------------------------------------"); System.out.println(str.length()); System.out.println(str.getBytes().length); String temp=new String(str.getBytes(), "UTF-8"); System.out.println(temp+"\t"+temp.length()); System.out .println(temp.getBytes().length); System.out .println("--------------------------------------------------"); String str2 = "abc中国"; System.out.println("第二部分-------------------------------------------"); System.out.println(str2.length()); System.out.println(str2.getBytes().length); System.out.println(new String(str2.getBytes(), "UTF-8").length()); System.out .println(new String(str2.getBytes(), "UTF-8").getBytes().length);
有的人运行结果是2、6、2、6;5、9、5、9
但有的人运行结果是2、4、3、4;5、7、6、7,也有可能运行结果是其他的值。完全相同的代码,运行结果却不同,这是为什么呢?
我们都知道,Java中String以Unicode的方式存储,这只是它在内存中的存储方式,一旦要使用这个String就需要转换成具体编码格式的表示形式,并且这个编码格式随源码文件的编码格式变化而变化。以上代码运行结果的根源就在这里。
请看下面的代码
//下面的字符串在GBK格式的源码文件里,字符串时GBK编码格式的 System.out.println("第一部分-------------------------------------------"); String str = "中国"; System.out.println(str.length()); // 这些应该都没有问题,关键在下面 System.out.println(str.getBytes().length);// 注意这里是得到的gbk的字节,一个汉字gbk编码是2个字节 System.out.println(new String(str.getBytes(), "UTF-8").length()); // 这里用得到的gbk的字节去转换成utf-8,需要注意的是一般情况下utf-8汉字占有3个字节,而acsll码在utf-8中是一个字节 // 而编码转换的规则是对字节进行扫描,如果可以转换成1个字节的ascll就优先转换,可以转换成2个字节就优先转换成两个字节的utf-8编码 // * 0xxxxxxx (00-7f) ascll // * 110xxxxx 10xxxxxx (c0-df)(80-bf) ascll和汉字之间的一些字符 // * 1110xxxx 10xxxxxx 10xxxxxx (e0-ef)(80-bf)(80-bf) 汉字 // * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx (f0-f7)(80-bf)(80-bf)(80-bf) // * 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx // (f8-fb)(80-bf)(80-bf)(80-bf)(80-bf) // * 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx // (fc-fd)(80-bf)(80-bf)(80-bf)(80-bf)(80-bf) // 仔细看上面的utf-8的编码表 再看通过getBytes(),最终得到的二进制码是 //11010110 11010000 10111001 11111010 // 第一个字节与第二个一直到最后字节组合不成utf-8编码(110开始的只有上面的第二行,但是下一个字节不是10******,因此要对第一个字节单独解码 // 再看第二个与第三个字节为11010000 10111001 刚好是一个上面的第二行的范围内,所以对他们两个进行一个utf-8解码 // 最后对11111010 进行解码 // 通过以上分析可以知道得到的utf-8格式的字符串时3个字符,所以长度是3 System.out .println(new String(str.getBytes(), "UTF-8").getBytes().length); System.out.println("第二部分-------------------------------------------"); String str2 = "abc中国"; System.out.println(str2.length()); System.out.println(str2.getBytes().length); System.out.println(new String(str2.getBytes(), "UTF-8").length()); // 01100001 01100010 01100011 11010110 11010000 10111001 11111010 // 一样从左到右去解码 显然前三个字节满足第一个范围分别解码为abc,后面就与上面的分析一样了 // 顺便说一句,如果不想得到乱码可以用getBytes("utf-8") System.out .println(new String(str2.getBytes(), "UTF-8").getBytes().length);
当你源代码文件的格式是UTF-8时,很符合一般的使用想法,但源码文件格式为GBK时,就会出现意想不到的结果。
相关推荐
java 字符串转16进制 16进制转字符串 将两个ASCII字符合成一个字节; java 字符串转16进制 16进制转字符串 将两个ASCII字符合成一个字节; java 字符串转16进制 16进制转字符串 将两个ASCII字符合成一个字节; java ...
浅谈Java字符串编程开发技术共3页.pdf.zip
浅谈Java字符串Java开发Java经验技巧共11页.pdf.zip
java字符串的各种编码转换. java字符串的各种编码转换
java字符串处理取出括号内的字符串 都是我自己试过可以用的j
java字符串编码转换和web中的字符串转换
java 字符串 详细实例代码 字符串检索 可改变字符串 字符串生成器 日期和时间字符串格式化
java压缩字符串
JAVA的字符串拼接与性能 概述:本文主要研究的是JAVA的字符串拼接的性能,原文中的测试代码在功能上并不等价,导致concat的测试意义不大。不过原作者在评论栏给了新的concat结果,如果有兴趣的同学建议自己修改代码...
java 字符串的加密 java 字符串的加密 java 字符串的加密
有关java里的一些字符串的总结,适合java初学者学习。
89.java字符串方法.zip89.java字符串方法.zip89.java字符串方法.zip89.java字符串方法.zip89.java字符串方法.zip89.java字符串方法.zip89.java字符串方法.zip89.java字符串方法.zip89.java字符串方法.zip89.java字符...
NDK开发之C语言调用Java构造方法、父类方法、返回中文字符串乱码问题案例详细解析。
java 分解字符串 java 分解字符串 java 分解字符串
JAVA 字符串 操作
不需要关心接受的字符串编码是UTF_8还是GBK,还是ios-8859-1,自动转换为utf-8编码格式,无需判断字符串原有编码,用法://处理编码String newStr = GetEncode.transcode(oldStr);
java中求字符串表达式的值看起来很伤脑筋,但如果你用BeanShell,一切都变得很简单。
96.java字符串反转案例.zip96.java字符串反转案例.zip96.java字符串反转案例.zip96.java字符串反转案例.zip96.java字符串反转案例.zip96.java字符串反转案例.zip96.java字符串反转案例.zip96.java字符串反转案例.zip...
Java字符串编码查询及转换,可将常用的一些编码格式转换成utf-8
29.java字符串+操作.zip29.java字符串+操作.zip29.java字符串+操作.zip29.java字符串+操作.zip29.java字符串+操作.zip29.java字符串+操作.zip29.java字符串+操作.zip29.java字符串+操作.zip29.java字符串+操作.zip29...