这两天抽时间又总结/整理了一下各类编码的实际编码方式,和在Java应用中的使用状况,在这里记录下来以便往后参考。
为了构成一个完整的对文字编码的认识和深刻把握,以便处理在Java开发过程当中遇到的各类问题,特别是乱码问题,我以为组成一个系列来描述和分析更好一些,包括三篇文章:
第一篇:JAVA字符编码系列一:Unicode,GBK,GB2312,UTF-8概念基础
第二篇:JAVA字符编码系列二:Unicode,ISO-8859,GBK,UTF-8编码及相互转换
第三篇:JAVA字符编码系列三:Java应用中的编码问题
第二篇:JAVA字符编码系列二:Unicode,ISO-8859-1,GBK,UTF-8编码及相互转换
1、函数介绍
在Java中,字符串用统一的Unicode编码,每一个字符占用两个字节,与编码有关的两个主要函数为:
1)将字符串用指定的编码集合解析成字节数组,完成Unicode-〉charsetName转换
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException
2)将字节数组以指定的编码集合构形成字符串,完成charsetName-〉Unicode转换
public String(byte[] bytes, String charsetName) throws UnsupportedEncodingException
2、Unicode与各编码之间的直接转换
下面以对中文字符串"a中文"的编码转换为例,来了解各类编码之间的转换
1)Unicode和GBK
测试结果以下,每一个汉字转换为两个字节,且是可逆的,即经过字节能够转换回字符串
String-GBK〉ByteArray:\u0061\u4E2D\u6587(a中文)-〉0x61 0xD6 0xD0 0xCE 0xC4
ByteArray-GBK〉String:0x61 0xD6 0xD0 0xCE 0xC4-〉\u0061\u4E2D\u6587(a中文)
2)Unicode和UTF-8
测试结果以下,每一个汉字转换为三个字节,且是可逆的,即经过字节能够转换回字符串
String-UTF-8〉ByteArray:\u0061\u4E2D\u6587(a中文)-〉0x61 0xE4 0xB8 0xAD 0xE6%0x96 0x87
ByteArray-UTF-8〉String:0x61 0xE4 0xB8 0xAD 0xE6%0x96 0x87-〉\u0061\u4E2D\u6587(a中文)
3)Unicode和ISO-8859-1
测试结果以下,当存在汉字时转换失败,非可逆,即经过字节不能再转换回字符串
String-ISO-8859-1〉ByteArray:\u0061\u4E2D\u6587(a中文)-〉0x61 0x3F 0x3F
ByteArray-ISO-8859-1〉String:0x61 0x3F 0x3F-〉\u0061\u003F\u003F(a??)
3、Unicode与各编码之间的交叉转换
在上面直接转换中,由字符串(Unicode)生成的字节数组,在构造回字符串时,使用的是正确的编码集合,若是使用的不是正确的编码集合会怎样呢?会正确构造吗?若是不能正确构造能有办法恢复吗?会信息丢失吗?
下面咱们就来看看这种状况,这部分能够说明在某些状况下虽然咱们最终正确显示告终果,但其间仍然进行了不正确的转换。
1)可以正确显示的中间不正确转换
咱们知道String-GBK〉ByteArray-GBK〉String是正确的,但若是咱们采用String-GBK〉ByteArray-ISO-8859-1〉String呢?经过测试结果以下:
String-GBK〉ByteArray-ISO-8859-1〉String:\u0061\u4E2D\u6587(a中文)-〉0x61 0xD6 0xD0 0xCE 0xC4-〉\u0061\u00D6\u00D0\u00CE\u00C4(a????)
这时咱们获得的字符串为?乱码“a????”,可是经过继续转换咱们仍然能够复原回正确的字符串“a中文”,过程以下:
String-GBK〉ByteArray-ISO-8859-1〉String-ISO-8859-1〉ByteArray-GBK〉String
对应:\u0061\u4E2D\u6587(a中文)-〉0x61 0xD6 0xD0 0xCE 0xC4-〉\u0061\u00D6\u00D0\u00CE\u00C4(a????)-〉0x61 0xD6 0xD0 0xCE 0xC4-〉\u0061\u4E2D\u6587(a中文)
也就是咱们在首次构造字符串时,咱们用了错误的编码集合获得了错误的乱码,可是咱们经过错上加错,再用错误的编码集合获取字节数组,而后再用正确的编码集合构造,就又恢复了正确的字符串。这时就属因而“可以正确显示的中间不正确转换”。在Jsp页面提交数据处理时经常发生这种状况。
此外可以正确显示的中间不正确转换还有:
String-UTF-8〉ByteArray-ISO-8859-1〉String-ISO-8859-1〉ByteArray-UTF-8〉String
和
String-UTF-8〉ByteArray-GBK〉String-GBK〉ByteArray-UTF-8〉String
对应:\u0061\u4E2D\u6587(a中文)-〉0x61 0xE4 0xB8 0xAD 0xE6%0x96 0x87-〉\u0061\u6D93\uE15F\u6783(a涓枃)-〉0x61 0xE4 0xB8 0xAD 0xE6%0x96 0x87-〉\u0061\u4E2D\u6587(a中文)
4、编码过程当中错误诊断参考
1)一个汉字对应一个问号
在经过ISO-8859-1从字符串获取字节数组时,因为一个Unicode转换成一个byte,当遇到不认识的Unicode时,转换为0x3F,这样不管用哪一种编码构造时都会产生一个?乱码。
2)一个汉字对应两个问号
在经过GBK从字符串获取字节数组时,因为一个Unicode转换成两个byte,若是此时用ISO-8859-1或用UTF-8构造字符串就会出现两个问号。
如果经过ISO-8859-1构造能够再经过上面所说的错上加错恢复(即再经过从ISO-8859-1解析,用GBK构造);
如果经过UTF-8构造则会产生Unicode字符"\uFFFD",不能恢复,若再经过String-UTF-8〉ByteArray-GBK〉String,则会出现杂码,如a锟斤拷锟斤拷
3)一个汉字对应三个问号
在经过UTF-8从字符串获取字节数组时,因为一个Unicode转换成三个byte,若是此时用ISO-8859-1构造字符串就会出现三个问号;用GBK构造字符串就会出现杂码,如a涓枃。数组
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/qinysong/archive/2006/09/05/1179489.aspxide