• 【JAVA编码】 JAVA字符编码系列二:Unicode,ISO-8859,GBK,UTF-8编码及相互转换


    http://blog.csdn.net/qinysong/article/details/1179489

    这两天抽时间又总结/整理了一下各种编码的实际编码方式,和在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
    测试结果如下,每个汉字转换为两个字节,且是可逆的,即通过字节可以转换回字符串
    StringGBKByteArray:/u0061/u4E2D/u6587(a中文)-〉0x61 0xD6 0xD0 0xCE 0xC4
    ByteArrayGBKString:0x61 0xD6 0xD0 0xCE 0xC4-〉/u0061/u4E2D/u6587(a中文)
     
    2)Unicode和UTF-8
    测试结果如下,每个汉字转换为三个字节,且是可逆的,即通过字节可以转换回字符串
    StringUTF-8ByteArray:/u0061/u4E2D/u6587(a中文)-〉0x61 0xE4 0xB8 0xAD 0xE6%0x96 0x87
    ByteArrayUTF-8String:0x61 0xE4 0xB8 0xAD 0xE6%0x96 0x87-〉/u0061/u4E2D/u6587(a中文)
    3)Unicode和ISO-8859-1
    测试结果如下,当存在汉字时转换失败,非可逆,即通过字节不能再转换回字符串
    StringISO-8859-1ByteArray:/u0061/u4E2D/u6587(a中文)-〉0x61 0x3F 0x3F
    ByteArrayISO-8859-1String:0x61 0x3F 0x3F-〉/u0061/u003F/u003F(a??)
    3、Unicode与各编码之间的交叉转换
    在上面直接转换中,由字符串(Unicode)生成的字节数组,在构造回字符串时,使用的是正确的编码集合,如果使用的不是正确的编码集合会怎样呢?会正确构造吗?如果不能正确构造能有办法恢复吗?会信息丢失吗?
     
    下面我们就来看看这种情况,这部分可以说明在某些情况下虽然我们最终正确显示了结果,但其间仍然进行了不正确的转换。
     
    1)能够正确显示的中间不正确转换
    我们知道StringGBKByteArrayGBKString是正确的,但如果我们采用StringGBKByteArrayISO-8859-1String呢?通过测试结果如下:
    StringGBKByteArrayISO-8859-1String:/u0061/u4E2D/u6587(a中文)-〉0x61 0xD6 0xD0 0xCE 0xC4-〉/u0061/u00D6/u00D0/u00CE/u00C4(a????)
     
    这时我们得到的字符串为?乱码“a????”,但是通过继续转换我们仍然可以复原回正确的字符串“a中文”,过程如下:
    StringGBKByteArrayISO-8859-1StringISO-8859-1ByteArrayGBKString
    对应:/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页面提交数据处理时常常发生这种情况。
     
    此外能够正确显示的中间不正确转换还有:
    StringUTF-8ByteArrayISO-8859-1StringISO-8859-1ByteArrayUTF-8String
    StringUTF-8ByteArrayGBKStringGBKByteArrayUTF-8String
    对应:/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涓�枃。
  • 相关阅读:
    洛谷 P1226 【模板】快速幂||取余运算 题解
    洛谷 P2678 跳石头 题解
    洛谷 P2615 神奇的幻方 题解
    洛谷 P1083 借教室 题解
    洛谷 P1076 寻宝 题解
    洛谷 UVA10298 Power Strings 题解
    洛谷 P3375 【模板】KMP字符串匹配 题解
    Kafka Shell基本命令
    Mybatis与Hibernate的详细对比
    MyBatis简介
  • 原文地址:https://www.cnblogs.com/eaglegeek/p/4557828.html
Copyright © 2020-2023  润新知