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する、という巧みな方法で完成する.
コード:
最近のプロジェクトでは、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 }