先看下面这段代码的运行结果
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编写系统中文显示问题及其处理.pdf" JAVA 编写系统中文显示问题是指在使用 JAVA 语言进行系统编程时遇到的中文显示乱码问题。这些问题包括浏览器页面乱码、表单数据提交时的乱码、数据库中信息不能正确...
简单点就是string是字符(串)… 而array是数组…可以放数字啊,字符啊等一系列... //各整数作为unicode编码,并连接成字符串。 var str1 = “liu”.localecompare(“zhan”);//按本系统提供的默认比较规则比较当前字符串
3. 从字符串中逐个读取字节:使用StringReader类,将字符串转换为字符流,然后调用read()方法按字符读取。 Java的输入输出流还包括许多其他类型的流,如FileInputStream和FileOutputStream用于文件操作,Socket...
此外,Java 9引入了字符串的重复字符串优化(String Duplication Optimization),如果连续创建两个内容相同的字符串,JVM会直接返回第一个字符串的引用,以减少内存开销。 了解这些内部机制后,程序员可以在编码时...
Java中的转义字符是编程时经常需要使用到的知识点,它允许程序员在字符串中包含一些特殊的字符。本文将深入探讨Java转义字符的使用,尤其是涉及正则表达式中使用的转义符。 首先,转义字符在Java中是通过反斜杠“\...
5. **处理JDBC连接**:确保JDBC连接字符串中也指定了正确的字符集,例如: ```java jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8 ``` 除了上述基本解决方案,还有其他可能导致乱码的...
JSON中的字符串与C语言或Java中的字符串非常相似。 数值在JSON中与C语言或Java中的数值也很相似,只是排除了未使用的八进制和十六进制格式,并忽略了一些编码细节。 在JSON中,可以向任何符号之间插入空白(空格、...
若需换行,建议选择在操作符和标点符号后进行,尤其是在逗号之后换行,而避免在变量名、数字或字符串等符号之后换行。这样做可以防止在进行复制粘贴操作时产生错误,并且提升代码的易读性。 4. 缩进和注释:缩进是...
1. **字符编码**:在JNI中传递字符串时要注意字符编码问题,默认情况下,Java使用UTF-16编码,而C/C++则通常使用ASCII或UTF-8。 2. **转换方法**:可以使用`GetStringUTFChars`和`ReleaseStringUTFChars`来获取和...
1. **字符串资源管理**: - 应将所有可复用的文本内容放入`string.xml`文件中。这样做可以方便统一管理和修改,例如,如果需要将“保存”按钮的文本改为“提交”,只需更改`string.xml`中对应条目的值,而无需遍历...
此外,值得注意的是,由于MySQL的表可能采用UTF-8编码,而Excel可能默认使用GBK编码,为了避免导出的Excel文件打开时出现乱码,需要在`INTO OUTFILE`语句中指定字符集为GBK。这确保了数据导出后能正确显示。 补充一...
4. 最后,确保应用程序连接MySQL时也使用utf8mb4编码,例如在Java或PHP的数据库连接字符串中指定字符集。 需要注意的是,切换到utf8mb4可能会增加存储空间的需求,因为每个字符可能需要更多的字节。此外,如果你的...
第6章 序列:字符串、列表和元组 6.1 序列 6.2 字符串 6.3 字符串和操作符 6.4 只适用于字符串的操作符 6.5 内建函数 6.6 字符串内建函数 6.7 字符串的独特特性 6.8 ...
数组允许我们在一个单一的变量中存储多个值,这些值可以是数字、字符串、对象等任何JavaScript的数据类型。JavaScript中的数组与其他强类型语言(如Java)的不同之处在于,它允许存储不同类型的值在同一数组中,且...
6.4.2 字符串模板: 更简单的替代品 6.4.3 原始字符串操作符(r/R) 6.4.4 Unicode字符串操作符(u/U) 6.5 内建函数 6.5.1 标准类型函数 6.5.2 序列类型函数 6.5.3 字符串类型函数...
- 比如,可以使用Groovy的字符串操作、正则表达式等来提取方法参数,并自动构建注释中的参数列表。 - 脚本可以在模板变量部分编写,例如`groovyScript("def methodName=\"${_1}\"; def result='*@Method:'+method...
最后,按照OAuth签名的规则,将排序后的参数字符串与密钥(consumer secret和token secret组合)进行HMAC-SHA256哈希运算,生成签名。这个签名将作为请求头的一部分发送,验证服务器端的身份。 4. **构建OAuth请求...