来自-IBM developworks
实际上汉字问题并没有那么多“问题”。说来说去都是大家在Unicode应用过程中自己搞迷糊了。我曾经给外交部做过一个CMS系统Demo,系统中同时支持所有Unicode支持的国家和语言,实际上并不难。
坚持一个原则:保证编码一致性。
无论从存储环节(比如文件、数据库)、网络传输环节(传出、传入),还是特别的系统的编码解码环节(例如使用某个XMLParser或自己的应用系统),每个环节管好自己:input的数据如果是A编码,那么就用A编码Decode,然后可以以任何编码Output。下一个环节得到后,一样的按照上一个环节的编码进行解码(理解)即可。
就好比大学里朋友们经常玩的一个游戏:大家围成一圈用各自的方言传话,到最后一个看看是否和原话相同。这个游戏之所以有趣,就是因为大家的方言不同,理解上一个人的说话出现了问题,于是往下传就出错了。(电视里也经常有这样的游戏,比如用手语等)
举个例子:如果网页中用了GB2312的编码,此时用户如果用IE和支持Unicode的输入法填写了一个form,提交后jsp应该用什么编码理解呢?显然是GB2312。呵呵,这里面有一个有意思的事情就是如果你在简体中文环境下,在BIG5编码的Web中提交form,JSP应该用BIG5来“理解”它!(去台湾bbs关税其实不用安装特别的软件的,用微软拼音输入法并选择繁体字即可,IE会自动转码)
JSP得到传递过来的参数,如果按照正确的编码进行解码,此时要写入数据库,该用什么编码呢?本来无所谓,你用编码A写入数据库,等程序从数据库取出来的时候也用A解码即可,但对于Oracle和SQLServer的不同驱动程序有些不同——有的驱动程序会对你传入的数据按照数据库的代码设置进行“解释”,中间转了一次码。所以需要测试一下,如果没有发生这样的情况,那么只需要用写入数据库的编码来理解从数据库读出的数据即可。随后,JSP“拿着”已经“正确理解”的数据,可以“翻译”成任何别的编码再告诉下一个环节——浏览器。此时,你的JSP输出的如果是BIG5的string,那么该Web的编码也需要是BIG5,否则浏览器会用错误的方式去“理解”,造成乱码。
IBM developworks上的文章仔细的分析了内码、字符集、字库之间的关系,不太明白的可以好好看看。其实很多情况下我们所谓的“汉字问题”不是内码的问题,有时候是字库混淆了我们的理解——比如说繁体字未必就是BIG5码!日文字未必就是JIS字符集!
我们只要记住遵循“脱衣法则”,编码和解码之间按顺序匹配进行就不会乱了。
如果一个环节和另外一个环节之间,不知道是什么意外的打乱了你的匹配,其实不说明我上面说的有错误,关键是检查一下你所用的软件环境,是不是你漏掉了某个环节的编码匹配——比如xmlparser、application server的编码设置。
hehe 当时为了调试那套CMS的多语种并存问题,加班干到半夜,一直在看IBMDevelopworks的各种文章。一个工程师找来了各个国家的国家代码、字符代码研究,而我相信我的考虑是正确的,顺藤摸瓜一个环节一个环节地找,最后找出Cocoon和Apache的一个设置,以及我们所用的MS JDBC for SQLServer2000不需要特别进行编码——因为它自己对传入传出的编码已经成对匹配(或不进行编码),另外一个驱动则没有成对编码解码。
实际上道理很简单啊:Unicode和Java出来之前,我们做那些网络通讯的软件的时候无论二进制还是ASCII方式,不都能正常使用么(只是不涉及到我们遇到的多语种并存问题)?所以关键在对同一个环节的input和output,你怎么编码就要怎么解码。
剩下的问题,只是熟悉你所写的应用的各个编码/解码环节。另外,写代码时显式编码是一个好习惯。