本文写于 12 年前(2013 年 12 月),部分内容可能已经过时。
今天遇到一个诡异的编码问题:我们这边一个客户端A调用某个网关B,网关调用某个服务C,服务C又调用服务D。结果发现收到的数据有中文乱码。但是这个乱码和用错编码的乱码很不同:大部分都是正确的,就是几个字符是乱码(基本都是’?’)。在A直接调用D,编码没有问题。说明A和D都是同一种编码(确定是utf-8编码)。那么就是中间的B和C编码出问题了。于是确定了一下B和C的编码,果然B是utf-8,C是GBK。C的编码与大家都不一致,所以会出现这个问题。
但是这里有个诡异的问题,就是在一个调用串中,即使每个调用方的编解码都是约定好的,只要这条调用串的编码不一致(而且是多字节编码方式的),就会出现乱码问题。看下面这个例子:
public class MultipleEncodingTest{
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "广东5天内确诊第4例人感染H7N9病例";
String encoding = "UTF-8";
String intermediateEncoding = "GBK";
System.out.println(str);
// 发送前编码
byte[] bs = str.getBytes(encoding);
// 中间服务解码再編码
str = new String(bs, intermediateEncoding);
bs = str.getBytes(intermediateEncoding);
// 接收端解码
str = new String(bs, encoding);
System.out.println(str);
}
}
打印结果:
广东5天内确诊第4例人感染H7N9病例
广东5天内确诊�?例人感染H7N9病例
如果把中间服务的编解码改成单字节的iso8859就不会有问题了:
String intermediateEncoding = "iso8859-1";
广东5天内确诊第4例人感染H7N9病例
广东5天内确诊第4例人感染H7N9病例
结论 多次编解码,一定要保证整个链条中的每个节点都是同样的编码,或者中间节点采用单字节的编解码方式(如iso8859-1)。
这篇对你有用?
在 GitHub 编辑
本文由 arganzheng 创作,采用 CC BY 4.0 许可协议。在保留原文作者、署名以及完整原文链接(https://arganzheng.life/multiple-encoding-problem.html)的前提下,欢迎各种形式的转载、翻译或商业引用。
COMMENTS
评论存放在 GitHub Discussions, 用 GitHub 账号登录即可发表,支持 Markdown。 想针对正文某句话说?选中那段文字,点浮出的「评论」即可划线评论;觉得哪里写错了,发表时勾上「同时提交 Issue」。 有人回复你时 GitHub 会按你的通知设置发邮件,不用守在这里。