以字节码通信时的乱码

来源:互联网 发布:淘宝网怎么装修 编辑:程序博客网 时间:2024/06/10 21:16

我们在做Android或IOS移动端的时候,传输的Model用JSON解析,然后用HTTP通信传输到服务端,服务端再用JSON解析,中间没有涉及到编码的问题,那是因为HTTP默认编码是UTF-8(也就是我们的Model是转换成UTF-8字节流通信的,如果我们不直接使用现成的HTTP通信函数,而是使用Socket,我们就会发现,无论是否经过JSON解析,最后都是转换成byte字节流传输,而将本文转换成字节流默认使用UTF-8编码)。

现在在做的一个Android项目是802通信协议(不是HTTP通信协议),所以Android端和服务端通信是基于字节流的通信(只不过在头和未部加上一些额外信息罢了)。

既然是字节流的通信,那就涉及到编码的问题,虽然说都是byte传输,但是不同的编码转换成byte是不同的,比如下面一段程序:

try {    String a = "A";    byte[] b = a.getBytes("GBK");    byte[] c = a.getBytes("UTF-8");    for (int i=0;i<b.length;i++)        Log.e("bbbbbbbbbbbbb","" + b[i]);    Log.e("XXXXXXXXXX","XXXXXXXXX");    for (int i=0;i<c.length;i++)        Log.e("ccccccccccccc","" + c[i]);}catch (Exception e){}

得到的结果是:

08-04 14:52:18.580 1998-1998/com.gci.renttrainterminal E/bbbbbbbbbbbbb: -44
08-04 14:52:18.581 1998-1998/com.gci.renttrainterminal E/bbbbbbbbbbbbb: -63
08-04 14:52:18.581 1998-1998/com.gci.renttrainterminal E/bbbbbbbbbbbbb: 65
08-04 14:52:18.581 1998-1998/com.gci.renttrainterminal E/XXXXXXXXXX: XXXXXXXXX
08-04 14:52:18.581 1998-1998/com.gci.renttrainterminal E/ccccccccccccc: -25
08-04 14:52:18.581 1998-1998/com.gci.renttrainterminal E/ccccccccccccc: -78
08-04 14:52:18.581 1998-1998/com.gci.renttrainterminal E/ccccccccccccc: -92
08-04 14:52:18.581 1998-1998/com.gci.renttrainterminal E/ccccccccccccc: 65

很明显,“粤”用GBK编码是{-44,-63},而用UTF-8编码是{-25,-78,-92}(2对3的关系,所以直接一个String,用GBK编码,UTF-8解码,再用UTF-8编码再转换成GBK会乱码,详情请看http://blog.csdn.net/u010234516/article/details/52853214)。所以我们要和后台约定,有中文传输的接口(或某一个字段)要用GBK编码(还是UTF-8编码)(其他接口或其他字段用BCD或者ASCII或者用默认的UTF-8等等都可以)(之所以中文要说明用什么编码,是因为GBK和UTF-8编码的ASCII码是不一样的,转换成byte的个数也是不一样的,解码的判断也是不一样的)。


下面说明一下为什么中文用byte传输时是负数?

GBK采用双字节8位表示,总体编码范围为 8140 -- FEFE,首字节在 81 -- FE 之间,尾字节在 40 -- FE 之间。
ASCII是7位编码,只使用前7位,第8位补0,所以转换成整数始终为正数,而GBK是8位编码,也就是说一个字节中的第8位可以为1,如1010 1101,而将其转换成byte类型时,byte值为10101101,以补码存储,第8位被当成符号位,当然是负数了,值为:-83。
“何”字的GBK编码是:BA CE(1011 1010 1100 1110),两个字节第8位都为1,对byte类型来说,都被理解为最高位符号位。这样值就变成-70和-50了。

最后附上ASCII码表:

http://www.asciima.com

阅读全文
0 0
原创粉丝点击