Java中Unicode和编码的理解

我们经常会遇到编码问题。 Java 号称国际化的语言,是因为它的 class 文件采用 UTF-8 ,而 JVM 运行时使用 UTF-16 (至于为什么 JVM 中要采用 UTF-16 ,我没看过 相关的资料,但我猜可能是因为 JAVA里面一个字符 (char) 就是 16 位的 ,而UTF-16正是双字节编码),都是 unicode 的编码。 UTF-8采用一个或多个字节编码。

unicode 的目标就是能支持世界上所有的字符集,也就是说几乎所有的字符集包含的字符在 unicode 中都有对应的编码。在 unicode 中,字符与代码的映射关系,就是 unicode 字符集,称为 UCS(Unicode Character Set) ,每个 unicode 字符编码称为 code point (代码点?)。UTF-8  UTF-16 是不同的 UCS 编码方法, UTF 就是 UCS Transformation Format 

 Java 中, String  getBytes() 方法就是对特定的字符串 (unicode) 按照给定的字符集进行编码(encode,可以比喻成加密), new String() 则可以按照某个字符集将字节流转换回 unicode decode,解密)。 Java 里面的每一个 String 都是 unicode 编码。

再来看Web页面,如果不做特殊处理, Form 表单的提交就按照页面的 ContentType 设置中的字符集进行编码转换,发送到后台,后台必须利用 req.setCharacterEncoding 来指定参数的编码格式 ( 不同的应用服务器应有不同的指定方式 ) ,才能正确解码。

Java 里面的 encode  decode 都是相对于 unicode 而言的, encode 的意思是将 char[] --> XXX Encoding byte[]  decode 就是由 XXX Encoding byte[] --> char[] 。平常,当我们说 “  GBK 编码转换为UTF-8 编码 ” 的时候,实际的意思就是: GBK Encoding byte[] --> UTF-8 Encoding byte[] ,这种转换只有在需要用 byte[] 传输数据的时候才有意义,否则便是毫无意义的。

首先要说明的一点是: Java 中的 String 对象就是一个 unicode 编码的字符串。

但是,我们通常会听到有人说: “ 我们需要将 String  ISO-8859-1 转换为 GBK 编码 ” ,这又是怎么回事呢?实际上,我们并不是  “  一个由 ISO-8859-1 编码的 String 转换为 GBK 编码的 String” ,反复说明的是, JAVA 中的 String 都是 unicode 编码的,所以不存在 “ISO- 8859-1 编码的 String”  “GBK 编码的 String” 这样的说法。而需要转换的唯一的原因是 String 进行了错误的编码。我们经常会碰到由 ISO-8859- 1 转换为诸如 GBK/UTF-8 等等这样的需求。所谓的转换过程是: String --> byte[] -->String 

也许 你非常清楚这个过程的代码: new String(text.getBytes("ISO-8859-1"),"GBK") 。但是,要真正理解起来并不是那么简单。表面上看似乎很容易理解, 不就是将 text String 对象按照 ISO-8859-1 的方式编码为byte[] 然后再把它按照 GBK 的方式转换为 String 吗?但是这句代码很容易会被误解为: “  text String ISO-8859-1 转换为 GBK 编码” ,这种说法是错误的。难道你见过用这样的代码: new String(text.getBytes("GBK"),"UTF-8") 来对 String 进行编码转换的吗?

之所以你会经常看到 new String(text.getBytes("ISO-8859-1"),"GBK") 这句代码,是因为一个 GBK 的字节流被错误地以 ISO-8859- 1 的方式转换为 String  unicode )了!发生这种情况最普遍的地方是一个GBK 编码的网页向后台提交数据的时候,就有可能会看到这句代码的出 现。 GBK 的流被错误的当成ISO8859-1 的流,所以便得到了一个错误的 String 。由于 ISO8859-1 是单字节编码,所以每个字节被按照原样 转换为 String ,也就是说,虽然这是一个错误的转换,但编码没有改变,所以我们仍然有机会把编码转换回来!所以那句经典的 new String(text.getBytes("ISO-8859-1"),"GBK") 便出现了。

如果系统误以为是其它编码格式,就有可能再也转换不回来了,因为编码转换并不是负负得正那么简单的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值