在打印单据的时候,有两个汉字“玥”和“芃”,始终显示为“?”,这一问题困扰了业务人员一段时间了。以前没有空,就没有投入精力去查原因,上次得了空,终于把这个问题解决掉了。
这个乱码的汉字从哪里来的呢?首先是业务人员通过一个遗留的PHP应用,输入到一个mysql 4数据库中,然后我们的java程序从这个mysql 4中读取,再写入到新的mysql5的数据库中,最后通过java程序生成html在用户的浏览器里显示,结果就看到了这两个汉字乱码。那么这个问题如何解决呢?
只有两个汉字乱码,而不是所有的汉字都乱码,所以我们的程序一定使用了一种包含汉字较少的字符集,而这个出错的汉字恰好不在此字符集中,否则,就应当是大部分汉字乱码,而不仅仅是这两个了。很自然的就让人想到了 gb2312, gbk, gb18030, utf8等字符集之间的关系。其中gb2312中只有六千多个汉字,其它几个字符集支持的汉字数相差不多,我们程序一定是在该使用gbk, gb18030或utf8的地方使用了含有汉字较少的gb2312。
经查阅相关文档,果然发现那两个汉字都不在gb2312里,而在gbk, utf8字符集里。我们的mysql5使用的utf8字符集,生成的html也是utf8编码,如果mysql5中的汉字是正确的话,那么就应该能正常显示,因此,数据进入mysql5的时候就应该出错了。java程序在连接mysql5的时候,在jdbc连接中设置了utf8,所以如果从mysql4数据库中读取出来的是正确的,就不应该写入出问题,因此数据在mysql4中可能就错了,也可能是从mysql4中读取的时候出错了。php的兄弟们说mysql的数据库是gb2312字符集的,mysql的配置文件里也是这么配置的。如果果真如此,那么这个两个汉字在mysql4的数据库中就应该不正常了,所有的程序读出之后都应该是乱码,可是php的录入程序那边确实是能正常显示的。我断定这个数据库里放的实际上是gbk字符集的汉字。选用和mysql4相对应的mysql j connector 3.14,并在jdbc连接url里设置了characterEncoding=gbk,读出来的仍旧不正确!查阅了mysql j connector的文档,原来3 版本的mysql connector根本就不支持characterEncoding这个选项。看来只能修改mysql的配置文件了。修改之后,果然这两个汉字可以正常显示了。
如果计算机是中国人发明的,那么计算机也许一开始就得支持汉字,就再也没有乱码的问题。如果世界上只有一种汉字的编码方案,也不会有乱码的问题,可惜汉字偏偏有很多中编码方案。所以在我们的程序中,一定得搞清楚,我们的汉字数据来自于哪里,使用的哪种编码,每个环节都得配置得当,否则就会有乱码问题。
对于一般的web应用来说,需要关心编码的地方有:
1,数据库以什么编码存储数据
2,程序使用什么字符集连接数据库
3,程序内部运行时使用什么字符集
4,程序源码使用什么字符集
5,生成的html文件是什么字符集
6,程序告知浏览器的字符集
如果以上这些地方的字符集有配置不正确的地方,往往就会乱码。
如果可以的话,最好在所有的地方都使用一种编码,比如对于java应用来说,在所有的地方都使用utf8编码,就可以解决问题。需要注意的是,在windows环境下,默认的文件编码是gb18030的,而不是utf8。
另外,极端鄙视故意使用生僻字火星文的脑残族!!