JSON数据传输 中文乱码问题 getByte()为罪魁祸首

编程入门 行业动态 更新时间:2024-10-15 18:24:41

JSON数据传输 中文乱码问题  getByte()为<a href=https://www.elefans.com/category/jswz/34/1764047.html style=罪魁祸首"/>

JSON数据传输 中文乱码问题 getByte()为罪魁祸首

1.出现场景:

netty客户端向服务端传输json字符串转为byte字节数组后的数据,但是服务器端接收到的后经过hexStr2Str转为10进制字符串后是乱码的json字符串,自然反序列化后的对象里的字段值也是乱码的。

2.罪魁祸首

 outData.writeBytes(data.getBytes());

data是json字符串

3.getBytes() 方法解读

/*** Encodes this {@code String} into a sequence of bytes using the* platform's default charset, storing the result into a new byte array.** <p> The behavior of this method when this string cannot be encoded in* the default charset is unspecified.  The {@link* java.nio.charset.CharsetEncoder} class should be used when more control* over the encoding process is required.** @return  The resultant byte array** @since      JDK1.1*/public byte[] getBytes() {return StringCoding.encode(value, 0, value.length);}

点进去跳到StringCoding中

static byte[] encode(char[] ca, int off, int len) {String csn = Charset.defaultCharset().name();try {// use charset name encode() variant which provides caching.return encode(csn, ca, off, len);} catch (UnsupportedEncodingException x) {warnUnsupportedCharset(csn);}try {return encode("ISO-8859-1", ca, off, len);} catch (UnsupportedEncodingException x) {// If this code is hit during VM initialization, MessageUtils is// the only way we will be able to get any kind of error message.MessageUtils.err("ISO-8859-1 charset not available: "+ x.toString());// If we can not find ISO-8859-1 (a required encoding) then things// are seriously wrong with the installation.System.exit(1);return null;}}

看这句String csn = Charset.defaultCharset().name();获取编码集,进入到Charset类

/*** Returns the default charset of this Java virtual machine.** <p> The default charset is determined during virtual-machine startup and* typically depends upon the locale and charset of the underlying* operating system.** @return  A charset object for the default charset** @since 1.5*/public static Charset defaultCharset() {if (defaultCharset == null) {synchronized (Charset.class) {String csn = AccessController.doPrivileged(new GetPropertyAction("file.encoding"));Charset cs = lookup(csn);if (cs != null)defaultCharset = cs;elsedefaultCharset = forName("UTF-8");}}return defaultCharset;}

可以看到,这里获取了file.encoding属性,并通过该属性查找到了对应的Charset对象,如果找不到该属性所对应的Charset,就默认返回utf-8,说明在值合理的情况下,file.encoding属性确实决定了所谓的默认编码。
java默认编码方案主要是由-Dfile.encoding来控制,如果没有指定那么就使用系统默认编码方案,如果指定但是不存在那么使用utf-8编码。

4.原因分析

《1》 先确定系统的编码集

我的客户端程序是运行在windows上

在Windows平台下,进入DOS窗口,输入:chcp

下表列出了所有支持的代码页及其国家(地区)或者语言: 
代码页       国家(地区)或语言 
437          美国 
708          阿拉伯文(ASMO 708)
720          阿拉伯文(DOS)
850          多语言(拉丁文 I) 
852          中欧(DOS) - 斯拉夫语(拉丁文 II) 
855          西里尔文(俄语) 
857          土耳其语 
860          葡萄牙语 
861          冰岛语 
862          希伯来文(DOS)
863          加拿大 - 法语 
865          日耳曼语 
866          俄语 - 西里尔文(DOS) 
869          现代希腊语
874          泰文(Windows)
932          日文(Shift-JIS)
936          中国 - 简体中文(GB2312)
949          韩文
950          繁体中文(Big5)
1200         Unicode        
1201         Unicode (Big-Endian)
1250         中欧(Windows)
1251         西里尔文(Windows)
1252         西欧(Windows)
1253         希腊文(Windows)
1254         土耳其文(Windows)
1255         希伯来文(Windows)
1256         阿拉伯文(Windows)
1257         波罗的海文(Windows)
1258         越南文(Windows)
20866        西里尔文(KOI8-R)
21866        西里尔文(KOI8-U)
28592        中欧(ISO)
28593        拉丁文 3 (ISO)
28594        波罗的海文(ISO)
28595        西里尔文(ISO)
28596        阿拉伯文(ISO)
28597        希腊文(ISO)
28598        希伯来文(ISO-Visual)
38598        希伯来文(ISO-Logical)
50000        用户定义的
50001        自动选择
50220        日文(JIS)
50221        日文(JIS-允许一个字节的片假名)
50222        日文(JIS-允许一个字节的片假名 - SO/SI)
50225        韩文(ISO)
50932        日文(自动选择)
50949        韩文(自动选择)
51932        日文(EUC)
51949        韩文(EUC)
52936        简体中文(HZ)
65000        Unicode (UTF-7)
65001        Unicode (UTF-8)

936,它对于的编码格式为GBK。

日志打印也证实了默认编码集是GBK:

2020-07-09 15:17:45 [Thread-648] INFO  c.q.q.qxzn.serviceImpl.IPCNVRDeviceServiceImpl - sendPDCResultDTO METHOD data = {"alarmInfo":"当前报警类型为:移动侦测, 报警通道个数:0, 报警通道号:","alarmTime":"2020-07-09 15:17:45","alarmType":"移动侦测","deviceIp":"192.168.0.62"}, length = 125
2020-07-09 15:17:45 [Thread-648] INFO  c.q.q.qxzn.serviceImpl.IPCNVRDeviceServiceImpl - 系统的默认编码集为:GBK
2020-07-09 15:17:45 [Thread-648] INFO  c.q.q.qxzn.serviceImpl.IPCNVRDeviceServiceImpl - data.getBytes().length = 154
2020-07-09 15:17:45 [Thread-648] INFO  c.q.q.qxzn.serviceImpl.IPCNVRDeviceServiceImpl - data.getBytes(ISO-8859-1).length = 125
2020-07-09 15:17:45 [Thread-648] INFO  c.q.q.qxzn.serviceImpl.IPCNVRDeviceServiceImpl - data.getBytes(UTF-8).length = 183

还打印了不同编码集下的获取的数组长度~~

《2》一个大坑就是

如果你是用的ide 代码编辑器里面去调试,你得到的永远是你内部jvm运行设置的编码环境,不是之后你真正部署的环境

所以你单纯在本地调试是很难发现问题的,我也是比对了服务器和本地的getByte()之后的byte数据长度,发现,我擦,还不一样长,然后嘞,本地就是好使~~ 蜜汁晕眩~~

5.解决方案

outData.writeBytes(JsonUtils.toJson(data).getBytes("UTF-8")

强制指定一个编码集,应该是以后都要养成这种习惯,不然挖坑埋自己~~

猛男落泪~~

更多推荐

JSON数据传输 中文乱码问题 getByte()为罪魁祸首

本文发布于:2024-03-11 15:13:21,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1729245.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:罪魁祸首   乱码   数据传输   中文   JSON

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!