博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
GBK编码和UTF-8编码互转的大坑
阅读量:6478 次
发布时间:2019-06-23

本文共 6732 字,大约阅读时间需要 22 分钟。

  这几天遇到一个BUG,问题很简单,解决却花了3、4天,特意记录下来。

  linux环境下,将默认编码设置为GBK以后,运行GBK编码的脚本,调用一个Java的jar包,然后总jar包中返回GBK字符串。但是不知道是哪里出了问题,返回的参数一直是问号乱码。

  放上脚本代码:

#!/bin/bash#str="\"$1       $2      $3\""str="\"http://iap.zh.gmcc.net/WebService/Notify.asmx    chenliang3      短信测试\""/flash/system/appr/SafeRun.bin 0 0 "/jre/bin/java -jar /appr/adiap.jar ${str}" 2>&1

  放上调试时的Java代码:

1 import java.io.ByteArrayOutputStream;  2 import java.net.MalformedURLException;  3   4 import sun.misc.BASE64Decoder;  5   6   7 public class text {  8   9     public static void main(String[] args) throws MalformedURLException, Exception{ 10  11         //byte[] fullByte1 = new String(str.getBytes("ISO-8859-1"), "UTF-8").getBytes("GBK");   12         //String fullStr = new String(fullByte1, "GBK"); 13          14         /* 假设环境是以GBK编码,将数据解码成GBK编码方式,但是任然是???乱码 15          * 可能一:数据在编码之前已经被编码成utf-8或者ISO-8859-1 16          * 可能二:在打包过程中,数据被重新编码 17          * String temp = new String(args[0].getBytes("GBK")); 18          * String temp1 = new String(args[0].getBytes("gb2312")); 19          */ 20          21         /* 测试是否打包影响编码,结果显示并非打包影响编码 22          * String a = new String("短信2测试"); 23          * String temp = new String(a.getBytes("GBK"),"utf-8"); 24          * String temp1 = new String(temp.getBytes("utf-8"),"GBK"); 25          * String ios = new String(a.getBytes("GBK"),"ISO-8859-1"); 26          * String ios2 = new String(ios.getBytes("ISO-8859-1"),"GBK"); 27          * 28          * System.out.print(a+'\r'); 29          * System.out.print(temp+'\r'); 30          * System.out.print(temp1+'\r'); 31          * System.out.print(ios+'\r'); 32          * System.out.print(ios2); 33          */ 34          35         /* 测试转为了ISO-8859-1还是UTF-8, 未能转回中文字符,应该转码成了UTF-8 36          * String ios2 = new String(args[0].getBytes("ISO-8859-1"),"GBK"); 37          */ 38          39         /*测试获取到字符串的准确编码,结果为UTF-8 40          * String whatsencode = getEncoding(args[0]); 41          * System.out.println(whatsencode); 42          */ 43          44          45         /* 是否能直接由UTF-8转为GBK,并未转回中文字符,任然为问好乱码 46          * String ios = new String(args[0].getBytes("UTF-8"),"GBK"); 47          * System.out.print(ios); 48          */ 49  50         /* 询问大学老师得知,main函数并不会对字符串编码进行变化, 51          * 那么会不会是脚本调用jar文件时会否进行编码转换 52          * 测试Windows下调用脚本是否会?乱码,脚本运行需要环境,测试不能,陷入困境 53          */ 54          55         /* 决定在shell脚本中将字符串转为base64编码以后传送过来,在java中解码完成后传送回脚本 56          * String a = new String("短信测试"); 57          * String txt64= getBASE64(a); 58          * System.out.println(txt64+'\r'); 59          */ 60          61          62         /* 63         String a = new String("短信测试"); 64         String txt64 = getEncoding(a); 65         System.out.println("-----------------"+'\r'); 66         System.out.println(txt64+'\r'); 67         String en = enUnicode(a); 68         System.out.println(en); 69         System.out.println(deUnicode(en)); 70         */ 71         System.out.println("-----------------"+'\r'); 72         System.out.println(enUnicode("tszQxbLiytQ= 短信测试")); 73          74         /*将接收到的16进制字符串数组转为字符串再转为字节数组,交换高低位*/ 75          76         StringBuffer stob = new StringBuffer(); 77         for(int i =0;i
> 4)); 165 sb.append(hexString.charAt((bytes[i] & 0x0f) >> 0)); 166 } 167 return sb.toString(); 168 }169 public static String deUnicode(String bytes) { 170 ByteArrayOutputStream baos = new ByteArrayOutputStream( 171 bytes.length() / 2); 172 // 将每2位16进制整数组装成一个字节 173 for (int i = 0; i < bytes.length(); i += 2) 174 baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString 175 .indexOf(bytes.charAt(i + 1)))); 176 return new String(baos.toByteArray()); 177 }178 179 /*对获得的16进制数据进行处理,高低位转换*/180 181 public static String swapHexHL(String temp){182 if (temp == null) return null;183 String high = (String) temp.subSequence(0,2);184 String low = (String) temp.subSequence(2,4);185 String newString = low +high;186 return newString;187 }188 /*去掉XML不认可的字符0x0-0x20*/189 public static String delcode(String in) {190 StringBuffer out = new StringBuffer(); // Used to hold the output.191 char current; // Used to reference the current character.192 if (in == null || ("".equals(in)))193 return ""; // vacancy test.194 for (int i = 0; i < in.length(); i++) {195 current = in.charAt(i);196 if ((current == 0x9) || (current == 0xA) || (current == 0xD)197 || ((current > 0x20) && (current <= 0xD7FF))198 || ((current >= 0xE000) && (current <= 0xFFFD))199 || ((current >= 0x10000) && (current <= 0x10FFFF))200 || (current < 0x0))201 out.append(current);202 }203 return out.toString().trim();204 }205 }

  放上从网上找来的乱码分析:

一个汉字对应两个问号在通过GBK从字符串获取字节数组时,由于一个Unicode转换成两个byte,如果此时用ISO-8859-1或用UTF-8构造字符串就会出现两个问号。若是通过ISO-8859-1构造可以再通过上面所说的错上加错恢复(即再通过从ISO-8859-1解析,用GBK构造);若是通过UTF-8构造则会产生Unicode字符"\uFFFD",不能恢复,若再通过String-UTF-8〉ByteArray-GBK〉String,则会出现杂码,如a锟斤拷锟斤拷编码过程中错误诊断参考1)一个汉字对应一个问号在通过ISO-8859-1从字符串获取字节数组时,由于一个Unicode转换成一个byte,当遇到不认识的Unicode时,转换为0x3F,这样无论用哪种编码构造时都会产生一个?乱码。2)一个汉字对应两个问号在通过GBK从字符串获取字节数组时,由于一个Unicode转换成两个byte,如果此时用ISO-8859-1或用UTF-8构造字符串就会出现两个问号。若是通过ISO-8859-1构造可以再通过上面所说的错上加错恢复(即再通过从ISO-8859-1解析,用GBK构造);若是通过UTF-8构造则会产生Unicode字符"\uFFFD",不能恢复,若再通过String-UTF-8〉ByteArray-GBK〉String,则会出现杂码,如a锟斤拷锟斤拷3)一个汉字对应三个问号 在通过UTF-8从字符串获取字节数组时,由于一个Unicode转换成三个byte,如果此时用ISO-8859-1构造字符串就会出现三个问号; 用GBK构造字符串就会出现杂码,如a涓 枃

  最后还是没有解决乱码的问题,而是通过将字符串转16进制,在Java中转回的方式实现结果

  放上最后的脚本代码:

 

1 #!/bin/bash2 str1="\"$1    $2\""    //$1,$2,$3,是运行脚本时传送的参数3 str2="$3"4 str3=`echo ${str2} | od -h`5 str4=`echo ${str3:8}`6 /flash/system/appr/SafeRun.bin 0 0 "/jre/bin/java -jar /appr/adiap.jar ${str1} ${str4}" 2>&1

 

 

一个汉字对应两个问号
在通过GBK从字符串获取字节数组时,由于一个Unicode转换成两个byte,如果此时用ISO-8859-1或用UTF-8构造字符串就会出现两个问号。
若是通过ISO-8859-1构造可以再通过上面所说的错上加错恢复(即再通过从ISO-8859-1解析,用GBK构造);若是通过UTF-8构造则会产生Unicode字符"\uFFFD",不能恢复,若再通过String-UTF-8〉ByteArray-GBK〉String,则会出现杂码,如a锟斤拷锟斤拷
编码过程中错误诊断参考1)一个汉字对应一个问号在通过ISO-8859-1从字符串获取字节数组时,由于一个Unicode转换成一个byte,当遇到不认识的Unicode时,转换为0x3F,这样无论用哪种编码构造时都会产生一个?乱码。
2)一个汉字对应两个问号
在通过GBK从字符串获取字节数组时,由于一个Unicode转换成两个byte,如果此时用ISO-8859-1或用UTF-8构造字符串就会出现两个问号。
若是通过ISO-8859-1构造可以再通过上面所说的错上加错恢复(即再通过从ISO-8859-1解析,用GBK构造);若是通过UTF-8构造则会产生Unicode字符"\uFFFD",不能恢复,若再通过String-UTF-8〉ByteArray-GBK〉String,则会出现杂码,如a锟斤拷锟斤拷
3)一个汉字对应三个问号在通过UTF-8从字符串获取字节数组时,由于一个Unicode转换成三个byte,如果此时用ISO-8859-1构造字符串就会出现三个问号;用GBK构造字符串就会出现杂码,如a涓 枃

转载于:https://www.cnblogs.com/blitheG/p/5606475.html

你可能感兴趣的文章
poj2378
查看>>
Java文件清单列表
查看>>
js url传值中文乱码之解决之道
查看>>
Trusty TEE
查看>>
[LeetCode] Reverse String 翻转字符串
查看>>
学习iOS【3】数组、词典和集合
查看>>
Hessian 原理分析--转
查看>>
转: 基于netty+ protobuf +spring + hibernate + jgroups开发的游戏服务端
查看>>
easyui传入map的数据前台展示出tree格式数据
查看>>
悲观的思考,乐观的生活.我们既需要思考的深度,也需要生活的温度!
查看>>
java.math.BigDecimal
查看>>
Vitamio中文API文档(4)—— VitamioInstaller
查看>>
yii框架常用url地址
查看>>
python3.4学习笔记(十六) windows下面安装easy_install和pip教程
查看>>
MyGUI 解析
查看>>
Linux中的ls命令详细使用
查看>>
graph-tool文档(一)- 快速开始使用Graph-tool - 2.属性映射、图的IO和Price网络
查看>>
easyui treegrid逐步加载
查看>>
GraphicsLab Project之辉光(Glare,Glow)效果 【转】
查看>>
<转>Python: __init__.py 用法
查看>>