中文数据网络传输转码与解码过程浅析
来源:互联网 发布:113什么意思 网络聊天 编辑:程序博客网 时间:2024/05/17 08:07
网络中传输数据,尤其是中文必然会遇到,转码与解码过程,中文产生乱码问题也就发生在该过程的某一环节,下面我将用代码的方式模拟整个转码和解码过程,相信理解此文之后,对所有中文乱码都会找到原因并处理之。在此之前,我们首先解一下网络发送数据的过程。以中文为例:中文的传输过程具体可能是:内存中unicode -> 编码阶段gbk, gb18030,gb2312,utf8 -> 到ISO8859-1 ->最后到可能的base64编码。其实传输ISO8859-1的字符就已经可以进行转换了,后面要进行Base64编码,我个人理解是为了网络发送和接受数据串简单,仅仅用基本的64个字符表示而已(个人观点,如有纰漏请不吝赐教!)。本例为了方便理解中文转码过程,没有进行base64的再次编码,关于base64编码与解码比较简单,请不理解的求助于网络。
下面我们开始上代码:
代码: Byte2HexUtil.java
package zmx.util;import java.math.BigInteger;/** * * @author zhangwenchao * */public class Byte2HexUtil { public static String bytes2hex01(byte[] bytes) { /** * 第一个参数的解释,记得一定要设置为1 * signum of the number (-1 for negative, 0 for zero, 1 for positive). */ BigInteger bigInteger = new BigInteger(1, bytes); return bigInteger.toString(16); } /** * 方式二 * * @param bytes * @return */ public static String bytes2hex02(byte[] bytes) { StringBuilder sb = new StringBuilder(); String tmp = null; for (byte b : bytes) { // 将每个字节与0xFF进行与运算,然后转化为10进制,然后借助于Integer再转化为16进制 tmp = Integer.toHexString(0xFF & b); if (tmp.length() == 1)// 每个字节8位,转为16进制标志,2个16进制位 { tmp = "0" + tmp; } sb.append(tmp); } return sb.toString(); } /** * 方式三 * * @param bytes * @return */ public static String bytes2hex03(byte[] bytes) { final String HEX = "0123456789abcdef"; StringBuilder sb = new StringBuilder(bytes.length * 2); for (byte b : bytes) { // 取出这个字节的高4位,然后与0x0f与运算,得到一个0-15之间的数据,通过HEX.charAt(0-15)即为16进制数 sb.append(HEX.charAt((b >> 4) & 0x0f)); // 取出这个字节的低位,与0x0f与运算,得到一个0-15之间的数据,通过HEX.charAt(0-15)即为16进制数 sb.append(HEX.charAt(b & 0x0f)); } return sb.toString(); } public static void main(String[] args) {byte[] bytes = {10,23,24,54};System.out.println(Byte2HexUtil.bytes2hex01(bytes)); System.out.println(Byte2HexUtil.bytes2hex02(bytes)); System.out.println(Byte2HexUtil.bytes2hex03(bytes));} }
这是一个工具类主要用于将byte[]数组转换为16进制字符串,16进制也可以理解为2进制的表现形式。
2、转码与解码过程:
package zmx.test;import zmx.util.Byte2HexUtil;public class T10 {public static void print(byte[] bytes) throws Exception{for(byte b: bytes){System.out.print(b+" "+ new String(new byte[]{b},"ISO8859-1")+" ");}System.out.println();}public static void print(String str) throws Exception{for(int i=0;i<str.length();i++){System.out.print(str.charAt(i)+" "+ ((byte)str.charAt(i))+" ");}System.out.println();} public static void main(String[] args) throws Exception { String chinese = "abc中文"; //中文字符串/*byte[] unicodes = chinese.getBytes("UNICODE");System.out.println(unicodes.length);print(unicodes);System.out.println(Byte2HexUtil.bytes2hex03(unicodes));*/byte[] bg2312 = chinese.getBytes("GB2312"); //根据某一中文编码(ASCall和ISO8859-1不包含中文)获取字节数组System.out.println(bg2312.length); //不同的中文格式编码获取的字节数组长度不同。print(bg2312);String sender = new String(bg2312,"ISO8859-1");System.out.println("发送的数据:"+sender); //将该字节数组根据ISO8859-1转换为网络可传输的形式System.out.println(Byte2HexUtil.bytes2hex03(bg2312)); //本质上就是传输编码之后的字节数组String receive = sender; //接受的数据System.out.println("接收的数据:"+receive);print(receive);byte[] receiveBytes = sender.getBytes("ISO8859-1");System.out.println(Byte2HexUtil.bytes2hex03(receiveBytes));System.out.println(new String(receiveBytes,"GB2312"));System.out.println(new String(receiveBytes,"GB2312").length()); }}
测试结果:
797 a 98 b 99 c -42 Ö -48 Ð -50 Î -60 Ä 发送的数据:abcÖÐÎÄ616263d6d0cec4接收的数据:abcÖÐÎÄa 97 b 98 c 99 Ö -42 Ð -48 Î -50 Ä -60 616263d6d0cec4abc中文5
通过代码我们可以很明显的看出,对于字符串:“abc中文”,在发送前我们可以将其转换为“unicode/gb2312/utf-8”等不同格式的字节码数组,例如:byte[] bg2312 = chinese.getBytes("GB2312");使用GB2312进行转码。将得到的字节数组准换成16进制字符串之后得到“616263d6d0cec4”,其中,英文占1个字节 中文占两个字节。根据gb2312的编码规范:61-a,62-b,63-c,d6d0-中,cece-文。使用其他编码格式转码也是同理。之后我们把该字节数组转换为网络中可以传输的ISO8859-1的字符串,使用String sender = new String(bg2312,"ISO8859-1");得到:abcÖÐÎÄ。其实给数据串就可以发送了。但是为了不产生特殊字符等,真正传输过程又做了base64变换。得到字符串之后在进行逆变换就可以恢复中文。
现在是不是对编码解码有了更深的理解,其实本质上就是这个简单,乱码也就是在变换过程中产生的,望读者对乱码产生原因多加分析。
- 中文数据网络传输转码与解码过程浅析
- 网络传输中文本传输与二进制传输与字符集
- 网络传输中文本传输与二进制传输与字符集
- 【转】HTTP传输二进制 数据编码解码
- 彻底解决网络传输过程中出现的中文乱码问题
- IP数据报传输与处理过程
- 自定义网络传输数据加密与解密
- QT 网络传输中文
- 网络传输过程
- 网络中 IP数据报 传输的过程
- 网络传输中,数据经历了哪些过程和转变
- 数据在网络7层中的传输过程
- 网络中IP数据报传输的过程
- 数据在网络中传输过程(arp-proxy)
- js中文转Unicode编码与解码
- WEBRTC视频网络传输到解码输出
- WEBRTC视频网络传输到解码输出
- 数据的网络传输
- vs 2015 编译cocos2dx 报错C1189 #error: Macro definition of snprintf conflicts with Standard Library func
- jquery datatable 取当前点击列的配置
- 糖果机器人_0005_day2_页面跳转_码全
- Spring结合三层架构
- 面试总结
- 中文数据网络传输转码与解码过程浅析
- PHP压缩图片函数
- java spring mvc 文件上传教程
- #QQ#5849000010000010912#QQ#
- Linux入门——适合初学者
- android学习好的文章及一些问题的解决方法书签整理
- Tomcat version 6.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 Web modules
- 飞机界面设置
- 【FAQ】ubuntu:java opensdk 7 如何升级到 8?