androidについてjarのjavanet.URLEncoder.encode()とjdkのjava.net.URLEncoder.Encode()の問題

9930 ワード

質問:
最近のプロジェクトでは、socketを使うので、コードが「GBK」になるのは避けられないが、androidを使っていることに気づいた.jarのjavanet.URLEncoder.Encode(「漢字」,「GBK」)を符号化すると最後の漢字の半分が失われることに気づき、例えば「福建省」が符号化すると「%C 3」になり、正しい「%C 3%d 6」ではなく「%C 3%d 6」になり、その後別のjavaプロジェクトでdemoが発見する.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配列を16進数の文字列に変換しただけで、各漢字の符号化をスペースで区切って、再取得の過程で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 }