UTF-8转码问题

        在与合作商进行基于http协议的消息传输时,遇到一个转码的问题。

        程序主要完成这样的工作:向对方发出一个http请求,对方在response里返回一串包含中文字符的字符串,程序将其解析,把中文字符传入下一个处理模块中。就这么简单!在编码方面,对方说并没有进行URLEncode编码,而是直接用getBytes(“UTF-8”)进行转码。

        通信自然是没有问题。问题是从response中取出的中文字符串进行转码后,得到的中文字符串包含乱码,即部分字符正常显示,部分是乱码。这种简单的http传输自然不会出现丢包的问题,于是便将问题锁定在转码上。先将对方的转码方法和我一开始使用转码方法贴出来。

对方转码方法:

1
2
3
4
5
6
7
8
9
String res = "0|";
 
if(responseMessage != null && responseMessage.getStatus() == SmsMessage.STATUS_NORMAL){
    res = res + responseMessage.getContentString();
}
 
res = new String(res.getBytes("UTF-8"), "UTF-8");
response.setContentType("text/plain; charset=utf-8");
response.getWriter().write(res);

 

我的转码方法:

1
2
byte[] bs = res.get().getStringContent().getBytes();
String result = new String(bs, "UTF-8");

(其中res.get()为mina框架中的webclient提供的方法,返回的是HttpResponseMessage)

 

        看了对方的代码后,感觉很奇怪。getBytes(“UTF-8”)是将字符串转为编码为”UTF-8”的字节码,new String(new byte[], “UTF-8”)是将字节码转为编码格式是”UTF-8”的字符串。这一来一回不就等于什么都没做吗?为了一探究竟,自己写了一个servlet,用他的方法对一个中文字符“感”进行处理。单步中发现,处理前后的字节码果然没有改变。当第一次使用getBytes(“UTF-8”)进行转码时,原先的两位字节码变成了三位;第二次转码又变成了两位,和处理前一摸一样。对方这样做,想是因为他们在构造出res后,并不能确定它的编码格式,所以来个统一编码。再来看我的程序。天!得到的字符串已经面目全非,其字节码数组变成了六位!一个“感”字变成了两个乱码字加两个单字节符号“愄1�7”。后面的时间里,对这个字符做了多次转码尝试,都无济于事。

        难道程序获取的字符本身就有问题?直接获取String会不会把response中的其他隐性信息也一并获取了?先取得字节码会如何呢?试一下!在HttpResponseMessage里有getContent()方法,返回就是一个字节数组,于是调用该方法。单步查看时发现,得到的字节码与getBytes(“UTF-8”)生成的字节码一摸一样。哈,有门儿!继续调用new String(new byte[], “UTF-8”)将其转换成字符。熟悉的“感”字跃然于屏幕之上,好亲切呀,把我感动的快哭了。一个简单的http请求响应操作,竟然被编码问题折腾了大半天!

        继续做了一些测试工作,使用最基本的URLConnection,发现若是直接从response中读取String,后面的转码操作都会有异常,而使用byte来读取就能避免这种异常。看来String中确实包含了一些字符内容之外的东西。是什么呢?

请留下评论

您的评论