关于android.jar里的java.net.URLEncoder.encode()和jdk里的java.net.URLEncoder.encode()出现的问题

问题:

最近做的项目中,因为要用到socket,所以难免就有编码的要"GBK",但是发 现在用android.jar里的java.net.URLEncoder.encode("汉字","GBK")做编码时发现会丢失最后一个汉字的一 半,如"闽"编码后成了"%C3"而不是正确的"%C3%d6",随后在另外一个java项目里demo,发现 java.net.URLEncoder.encode("汉字","GBK")不存在这个问题,就开始郁闷了...

尝试:

尝试1:发现jdk里的java.net.URLEncoder类里的实现和android.jar里的完全不一样,猜测是不是底层实现不一样才导致了上面的问题,随后将jdk里的java.net.URLEncoder类copy到我的项目里进行尝试,发现问题依旧,此思路尝试失败!

尝试2:通过发现可能是和不同的平台有关,我的项目使用的是android网络盒子,4.4.2,第三方厂商oem的系统,那别的android平台可以正确运行么?

开始尝试,使用另外一个小android项目里为java.net.URLEncoder.encode做了一个小demo的apk,在别的android手机上运行,发现可以正确运行,能得到正确的结果.说好的平台无关性么?原来还真和平台有关!!

问题原因:通过发现好像是String的getBytes()里使用了System.arraysCopy()这个native方法里将一个char的字节截取所致(具体也没太深究,等有空再来研究,项目急).

解决方案:

所 幸在这个项目里的传输数据只对汉字进行URLEncode,所以,做了一些工具将需要传输的数据中的汉字通过正则挑出,然后将汉字在使用编码前在这个只有 汉字的String后面加上随便一个String,如:"1",然后再取出时只要汉字部分的编码(这个编码也是个工具方法,只是将byte数组转化成十六 进制的字符串,然后将每个汉字的编码用空格隔开,再取的过程中使用String.spit()将每个汉字的编码形成String[]),然后将原来的 String的汉字和编码后汉字String进行replace,这个偷巧的方法完成.

代码:

 1
 2 static final String regEx = "[\\u4e00-\\u9fa5]+";
 3
 4 /**对数据内容为String的json字符串里的values里的汉字进行URLEncoding GBK的编码*/
 5 public static String encodingSocketData(String socketData){
 6
 7   ///判断有没有中文
 8   if ((!TextUtils.isEmpty(socketData)) && (socketData.getBytes().length != socketData.length())) {
 9     ArrayList<String> list = new ArrayList<String>();
10     Pattern p = Pattern.compile(regEx);
11     Matcher m = p.matcher(socketData);
12     while (m.find()) {
13       list.add(m.group(0));
14     }
15   for(int i=0;i<list.size();i++){
16     String oldStr = list.get(i);
17     String newStr = encoding(oldStr);
18     socketData = socketData.replaceFirst(oldStr, newStr);
19   }
20   }
21 return socketData;
22
23 }
24 /**主要处理字符串中汉字的编码,data必须是一个汉字或多个汉字相连的字符串形式*/
25 static String encoding(String data){
26   if(TextUtils.isEmpty(data)){
27     return data;
28   }else{
29     KTLog.e("data>>>转码前>>"+data);//test
30   int size = data.length();
31   String temp = null;
32   byte[] arrays =null;
33   try {
34     arrays = (data+"1").getBytes(CCSParams.SocketParams.SOCKET_DATA_PARSE_FORMAT);
35     String[] strArrays = SocketUtils.byteArray2HexStr(arrays, true).split(" ");
36     StringBuffer strb = new StringBuffer();
37   for(int i=0;i<size*2;i+=2){
38     strb.append(‘%‘).append(strArrays[i]).append(‘%‘).append(strArrays[i+1]);
39   }
40   temp = strb.toString();
41   } catch (UnsupportedEncodingException e) {
42     KTLog.e("encoding执行("+data+")异常", e);
43   }
44   return temp;
45   }
46 }
47
48 public static String byteArray2HexStr(byte[] bArray, boolean format) {
49   StringBuffer strb = null;
50   if (null != bArray) {
51     strb = new StringBuffer(bArray.length);
52   for (int i = 0; i < bArray.length; i++) {
53     String str = Integer.toHexString(0xFF & bArray[i]).trim();
54     if (str.length() < 2) {
55       strb.append("0");
56     }
57     strb.append(str);
58     if (format) {
59       strb.append(" ");
60     }
61   }
62   } else {
63     return null;
64   }
65   return strb.toString().trim();
66 }
时间: 2024-10-06 05:22:16

关于android.jar里的java.net.URLEncoder.encode()和jdk里的java.net.URLEncoder.encode()出现的问题的相关文章

Eclipse工程中Java Build Path中的JDK版本和Java Compiler Compiler compliance level的区别(转)

在这里记录一下在eclipse中比较容易搞混淆和设置错误的地方.如下图所示的功能: 最精准的解释如下: Build Path是运行时环境  Compiler是编译时环境  假设,你的代码用到泛型,Build Path环境为1.5,Compiler环境为1.4,那么会显示编译错误,无法编译:但是这样的web项目是可以在web容器中运行的,前提是你的容易支持1.5语法. Build Path里面是你的class文件的运行环境级别,非编译器需要使用到的,例如,如果用的1.4就不能使用泛型.而Compi

Collect preferences failed, class java/lang/AutoCloseable not found in D:\Program Files (x86)\Android\android-sdk\platforms\android-19\android.jar

Eclipse中出现这样的问题:Collect preferences failed, class java/lang/AutoCloseable not found in D:\Program Files (x86)\Android\android-sdk\platforms\android-19\android.jar 安卓手机通过数据线和电脑连接不能够在线调试. 问题解决: 将D:\android-sdk\sdk\tools\lib目录(安卓SDK的目录)下的plugin.prop文件修改

android sdk 编译--如何将源代码加入android.jar,以及make原理

首先是这个问题如何修改. 在/frameworks/base/Android.mk中,找到如下行:packages_to_document :=在该变量的赋值语句最后添加xxxxx (这里是你的包的名称,比如com/sina/ui,其实这里就是你的源代码在/frameworks/base/<你的模块>/java/下面的一部分路径,只要能够唯一的匹配到你的代码即可) 即可. 该添加的含义是使MAKE系统在制作OFF-LINE DOCUMENT时包含我们的package.以此类推,添加其他新的pa

混淆Android JAR包的方法

混淆Android JAR包的方法 - vurtne_ye的专栏 - 博客频道 - CSDN.NET 1)导出jar包 如何在eclipse上android工程中导出jar包?google,baidu.bing 2)混淆jar包,打乱代码 android的jar包跟普通的java的jar包不一样,我们不想打乱一些activity或者server等跟系统打交道的代码,这是因为如果把这些也混淆了,那你还需要搞清楚混淆后这些activity变成了什么名字,然后告诉使用你这个jar包的人androidm

Android Studio解决问题:Process &#39;command &#39;/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/bin/java&#39;&#39; finished with non-zero exit value 2

最近在结合百度地图.百度定位.高德导航时,遇到异常: Error:Execution failed for task ':app:dexWebDebug'. > com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/

Android见招拆招八:多次遇到的R.java编译问题

问题描述 R cannot be resolved to a variable 问题原因 android:id="@+id/15" 定义id时命名不规范导致了编译错误,不能使用数字,须使用英文字母 切记不能再犯. 另外,可能导致R cannot be resolved to a variable的还有其他原因,很多时候是由于各种原因R.java没有生成,排查方法如下 转载自http://blog.csdn.net/jason0539/article/details/9708025 1.

Android开发中出现的低级错误之没有android jar包

The type java.lang.Object cannot be resolved. It is indirectly referenced from required .class files 解决办法:相应的系统的jar包没有导入:选add External JARs...,添加android.jar. 为什么导入工程时候,android.jar包没有导入进来?现象就是所有工程都有问题. 解决办法:在系统的环境变量Path中增加E:\adt-bundle-windows-x86-201

Java基础念整理(jdk、jar、)

前世 java的历史来源背景 背景在网上百度随便都能找的到就不细说了,作为一个之前学习C++的程序员来说,学习java尽量对比学习,理解可以更加透彻. 首先:java相对C++摒弃了哪些特性,又增加了哪些特性? java的包.jdk.jar包.jre 包(package) package 特点 程序中如果有package语句,该语句一定是源文件中的第一条可执行语句: package语句的前面只能有注释或空行: 一个文件中最多只能有一条package语句: 包的名字有层次关系,各层之间以点分隔(上

自行修改android.jar使其包含隐藏api

1) 从指定版本的rom内获取到framework.jar 2) 解压framework.jar和android sdk内的android.jar 3) 将framework.jar解出来的东西拷到android.jar解出来的东西内,进行覆盖 4) 重新打包 5) 用新的android.jar替换原先的 方便起见,写了一个脚本来完成以上工作,其中解framework.jar用到dex2jar工具,请自行下载并配置环境变量 #!/bin/sh DEX=$1 AJAR=$2 OUT=$3 d2j-