`
剑锋凛冽
  • 浏览: 75524 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

浅谈Java字符串的编码问题

 
阅读更多

先看下面这段代码的运行结果

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编写系统中文显示问题及其处理.pdf" JAVA 编写系统中文显示问题是指在使用 JAVA 语言进行系统编程时遇到的中文显示乱码问题。这些问题包括浏览器页面乱码、表单数据提交时的乱码、数据库中信息不能正确...

    浅谈javascript中字符串String与数组Array

    简单点就是string是字符(串)… 而array是数组…可以放数字啊,字符啊等一系列... //各整数作为unicode编码,并连接成字符串。 var str1 = “liu”.localecompare(“zhan”);//按本系统提供的默认比较规则比较当前字符串

    2021-2022年收藏的精品资料软件工程师浅谈Java的输入输出流技术步骤说明.docx

    3. 从字符串中逐个读取字节:使用StringReader类,将字符串转换为字符流,然后调用read()方法按字符读取。 Java的输入输出流还包括许多其他类型的流,如FileInputStream和FileOutputStream用于文件操作,Socket...

    浅谈Java String内幕(上)

    此外,Java 9引入了字符串的重复字符串优化(String Duplication Optimization),如果连续创建两个内容相同的字符串,JVM会直接返回第一个字符串的引用,以减少内存开销。 了解这些内部机制后,程序员可以在编码时...

    浅谈Java转义符\\|

    Java中的转义字符是编程时经常需要使用到的知识点,它允许程序员在字符串中包含一些特殊的字符。本文将深入探讨Java转义字符的使用,尤其是涉及正则表达式中使用的转义符。 首先,转义字符在Java中是通过反斜杠“\...

    浅谈mysql的中文乱码问题

    5. **处理JDBC连接**:确保JDBC连接字符串中也指定了正确的字符集,例如: ```java jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8 ``` 除了上述基本解决方案,还有其他可能导致乱码的...

    JSON浅谈-2

    JSON中的字符串与C语言或Java中的字符串非常相似。 数值在JSON中与C语言或Java中的数值也很相似,只是排除了未使用的八进制和十六进制格式,并忽略了一些编码细节。 在JSON中,可以向任何符号之间插入空白(空格、...

    浅谈JavaScript编程语言的编码规范

    若需换行,建议选择在操作符和标点符号后进行,尤其是在逗号之后换行,而避免在变量名、数字或字符串等符号之后换行。这样做可以防止在进行复制粘贴操作时产生错误,并且提升代码的易读性。 4. 缩进和注释:缩进是...

    JavaJNI资料全整理含自己的常见问题总结.pdf

    1. **字符编码**:在JNI中传递字符串时要注意字符编码问题,默认情况下,Java使用UTF-16编码,而C/C++则通常使用ASCII或UTF-8。 2. **转换方法**:可以使用`GetStringUTFChars`和`ReleaseStringUTFChars`来获取和...

    浅谈Android编码规范及命名规范

    1. **字符串资源管理**: - 应将所有可复用的文本内容放入`string.xml`文件中。这样做可以方便统一管理和修改,例如,如果需要将“保存”按钮的文本改为“提交”,只需更改`string.xml`中对应条目的值,而无需遍历...

    浅谈mysql导出表数据到excel关于datetime的格式问题

    此外,值得注意的是,由于MySQL的表可能采用UTF-8编码,而Excel可能默认使用GBK编码,为了避免导出的Excel文件打开时出现乱码,需要在`INTO OUTFILE`语句中指定字符集为GBK。这确保了数据导出后能正确显示。 补充一...

    浅谈Mysql如何处理表情,MySql如何存储表情

    4. 最后,确保应用程序连接MySQL时也使用utf8mb4编码,例如在Java或PHP的数据库连接字符串中指定字符集。 需要注意的是,切换到utf8mb4可能会增加存储空间的需求,因为每个字符可能需要更多的字节。此外,如果你的...

    Python 核心编程 第二版

     第6章 序列:字符串、列表和元组   6.1 序列   6.2 字符串   6.3 字符串和操作符   6.4 只适用于字符串的操作符   6.5 内建函数   6.6 字符串内建函数   6.7 字符串的独特特性   6.8 ...

    浅谈Javascript数组(推荐)

    数组允许我们在一个单一的变量中存储多个值,这些值可以是数字、字符串、对象等任何JavaScript的数据类型。JavaScript中的数组与其他强类型语言(如Java)的不同之处在于,它允许存储不同类型的值在同一数组中,且...

    Python核心编程第二版

     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 字符串类型函数...

    浅谈idea live template高级知识_进阶(给方法,类,js方法添加注释)

    - 比如,可以使用Groovy的字符串操作、正则表达式等来提取方法参数,并自动构建注释中的参数列表。 - 脚本可以在模板变量部分编写,例如`groovyScript("def methodName=\"${_1}\"; def result='*@Method:'+method...

    jmeter 实现oauth1.0授权认证

    最后,按照OAuth签名的规则,将排序后的参数字符串与密钥(consumer secret和token secret组合)进行HMAC-SHA256哈希运算,生成签名。这个签名将作为请求头的一部分发送,验证服务器端的身份。 4. **构建OAuth请求...

Global site tag (gtag.js) - Google Analytics