一个字符编码问题的解决过程

来源:互联网 发布:轻量级c语言ide 编辑:程序博客网 时间:2024/04/30 08:34

最近被一个问题困扰了几天,现在回过头来整理思路才发现绕了不少弯路。

 

问题是这样的,我写了一个java程序从网上上抓取数据到sqlite上,这个程序是执行在linux环境下。之前一直执行的好好的,没有出现过中文乱码的现象,但是最近由于升级服务器把数据迁移到了新的环境上,导致再向sqlite中插入中文数据时就出现乱码,迁移系统时没有改动任何 linux上的配置,包括/etc/sysconfig/i18n和 /etc/profile下的编码,奇怪的是不仅新插入的数据是乱码,迁移之前的数据也有部分变成了乱码。 而且更为奇怪的是中文乱码只出现在数据库当中的一个表,另外的表不受影响。我猜测可能是抓取的网页的编码发生了变化,但是检查过后确定没有变化,而且java程序里面出入数据的代码也没有改动。我又想可能会是环境发生了变化,于是在本地(window7)测试了一下,发现导入的中文数据显示正常,可是一到了服务器上(centOS5.5)上导入的数据就又不对了。我实在是迷惑了,到底有什么办法能够解决这个编码的问题?

 

这个问题看似复杂,要考虑三个编码(操作系统的编码,数据库的编码,还有网页的编码),两个环节(从网页上抓取信息,将信息存到数据库中)到底是那个环节的问题呢?

 

其实解决起来并不难,关键是找对思路。首先, 通过本地和服务器上分别运行程序测试的结果,可以知道跟数据库没有关系,而且从网上也得知虽然sqlite是默认utf-8编码,但也可以兼容其他编码。

其次,考虑证券交易所每天都有很多人查看,所以网页上的编码不会轻易改变,既然之前的程序没有出现乱码,现在也应当不会乱码。

所以,出现问题只能是在操作系统的编码上了,而且问题出现的时间是在升级服务器之后,所以肯定跟服务器上的配置有关,所以首先检查linux上的字符编码配置,通过google得知,/etc/sysconfig/i18n是配置编码的文件,于是先修改他,这个地方有几项配置:

#LANG="en_US.UTF-8"
LANG="zh_CN.GB2312"
#LC_ALL="C"
LANGUAGE="zh_CN.GB18030:zh_CN.GB2312:zh_CN"
#SUPPORTED="en_US.UTF-8:en_US:en:C"
SUPPORTED="zh_CN.GB18030:zh_CN:zh"
#SYSFONT="latarcyrheb-sun16"
SYSFONT="lat0-sun16"
SYSFONTACM="8859-15"

 

最关键的是LANG,这个值是Java程序运行时默认的编码,在默认情况下是UTF-8,但是由于抓取的网页是中文的,所以要修改为GBK或者GB2312/GB18030,但是修改为哪个呢?

 

我先试了zh-CN.GB2312,发现数据完全不对,不仅控制台打印的信息不对,中文都是乱码,数据库里的数据也不对。

然后又试了试zh_CN.UTF-8,发现控制台的中文显示是对了,但是数据库的数据还是不对。

又试了试zh_CN.GBK,从控制台反馈的信息让我有点失望,怎么又是乱码。

再试了试zh_CN.GB18030,结果跟GB2312的一样。

于是,有点崩溃了~~

 

我又想会不会要在java程序中转换一下编码呢?虽然我觉得应该不会是java的问题,因为之前没转换编码也一样可以存储中文啊,但事到如今,什么也要试一下了,抱着一线希望,我尝试把抓取到的字符串用gbk解析成字节,再用utf-8组合成字符串,存进数据库。

结果没错,我又失望了。

存进去的字符显示不出来,全是问号什么的....

 

这下彻底崩溃...于是我暂时放弃....

 

之后过了一两天,我跟一个朋友讨论这个问题,他的一句话提醒了我,他说

“linux对GB2312不认,但认GBK。可以提醒系统GB2312就是GBK?”

我想有可能吧,我再试一试看,这时我想起我要抓取的三个表中 

香港下载的都是Big5,因为是英文版的,深圳是GBK,只有上海写的是GB2312. 

既然深圳GBK没有问题,那么不妨用GBK试一试,于是将LANG改为zh_CN.GBK,然后source /etc/sysconfig/i18n,再启动java程序,

 

控制台打印的信息仍然是乱码,再查看日志文件,也是乱码,再看看数据库里的数据,咦~~好像是对的。于是,把日志文件和数据库文件下载到本地,再用文本编辑器查看,咦~~这下又显示正常了。看来这里面有蹊跷啊。不过仔细一想,windows跟linux的编码本来也就不同,显示不正常也可以理解。于是再在linux上运行一次,结果还是一样。为什么控制台显示不对呢? 难道是putty的问题? 我又查了下google,发现还真的putty有字体设置,改为中文字体后,显示正常!  据此,我断定之前看到的种种乱码现象都是linux的编码所致,而且数据库也是兼容gbk编码的,只不过由于我的远程工具putty默认只支持utf-8,所以在控制台打印出来的成了乱码。

 

 

总结:最开始的思路是没错的,碰到跟字符编码有关的问题,先排除掉数据库的问题和程序的问题,可是为什么到后来开始怀疑之前的判断了呢? 可能是因为太相信自己的眼睛了吧,以为控制台打印出来的东西就一定是对的,其实控制台的信息也有错误的时候... 以后推翻自己的观点前还是多方面确认,如果当时多看一看日志文件,多看一看数据库里的记录,再多对比一下本地操作系统和远程操作系统的区别,就不会这样了吧... 

另外,多跟人讨论还是很有帮助的,虽然google 很强大,但也代替不了人的作用,多一个人就多一个思路,也许不一定对,但总比一个人死钻强,这点作为程序员尤其要注意哈!

 

原创粉丝点击