解析Java WEB中文乱码问题根源
2.1. 中文的编码
遗憾的是,早期的计算机设计者并没有考虑到计算机将应用到全世界的各个领域,正如他们设计的日期只能到1999年为止一样。当计算机在我国应用的时候,问题就出现了。ISO8859-1并不包括中文,而且成千上万的汉字显然无法用一个字节来表示。
其解决办法是双字节的GB2312码。因为要跟ISO8859-1码兼容,所以GB码一般以一种变长的EUC模式处理,即字符a的编码仍然和ISO8859-1一致,而汉字的编码,则用两个字节来表示。
很麻烦吗?如果只有这么麻烦的话,恐怕就不会有那么多中文问题了。
首先,由于GB2312收录的字符有限,甚至连总理的名字都无法表示,因此又出现了GBK和GB18030编码(需要注意的是GBK并非国家标准) 另外一些繁体字地区使用的BIG5编码,尽管原理类似,但是编码却不同,使得沟通非常困难。世界上其他地方,也有自己的双字节编码,字符编码成了“万马奔腾”的结局。如果大家各自用各自的,也就罢了,但是显然计算机专家不能容忍这种局面,于是,新的囊括几乎所以字符的双字节编码Unicode诞生了(其收录的字符仍然在增加中)。
Unicode?那UTF-8又是什么东东呢?因为Unicode的编码,和ISO8859-1并不兼容,a的ISO8859-1编码为0x41,而Unicode为 0x00 0x41。这样一来,那些长久以来积累的英文txt文件岂不是无法使用?而UTF-8是一种变长的编码,字母的编码和ISO8859-1完全一样,中文的编码,则用三个字节表示。
通常在文本文件中使用的都是UTF-8编码,而jdk内部的String对象,才是Unicode编码。Java从设计之初,就明确了其所有的String对象,必然是Unicode编码。而字符串写到文件之中,或者供网络传输使用的时候,总之不是JVM的String对象的时候,则可能是UTF-8或者GB2312编码。
所以汉字编码,有Unicode,GB2312和BIG5等形式。一个中文字符,在不同的软件不同的环境下,有不同的二进制值。虽然java String对象总是Unicode,但是J2EE是一个需要和很多应用系统打交道的环境,比如说,用户提交的数据,并不是java的String,而是浏览器提交的几个字节,配置文件的内容,是文件系统中的几个字节。
然而即使如此,故事仍远未结束。