j2me與.net WebService傳輸中文亂碼解決方法
自己站里一篇舊文http://www.591pic.com
左腳耐克,右腳阿迪達,記得在哪聽過這句話。
現在是左手N70,右手N95。
三月份做的那個移動物流項目進入收尾,突然要增加終端定位功能,在專用GPS設備上開發已經來不及了,公司決
定在手機終端上開發。就這樣,帶GPS模塊的機皇N95就屈尊到了我手里,小爽了一把。
正事歸正事,在原有模塊上做了一周多,碰到一個奇怪的問題。終端獲取GPS定位信息后,需要周期性上傳至服務
器,終端是通過JSR172來調用服務端的WEBSERVICE,當傳入的參數為中文時,服務器數據庫中記錄的數據就為
亂碼,當參數為英文或阿拉伯數字時,就正常(廢話:英文都成亂碼,那計算機不是瘋了?!呵呵)
初步判斷是由于終端和服務端碼制不同造成的。
比如:public String sendMessage(String message) 有一個這樣的方法。
當傳入參數message為中文時,服務器端接收到的就是亂碼,但該方法卻能正常返回中文
查詢到的手機系統編碼是:iso-8859-1,服務器端的編碼方式為UTF-8。
嘗試過在手機端將字符串用iso-8859-1打成字節數組,然后用UTF-8組成新字符串,
如: message=new String(message.getBytes("iso-8859-1"),"UTF-8"); 服務器端收到的也一樣是亂碼。
在將iso8859-1,utf-8,gbk這三種編解碼排列組合的試過一次后,仍然還是亂碼。
一天過去了,
google之,文檔查詢之,“牛人”咨詢之,求神拜佛之,頭撞南墻之, 啥沒解決之。
翌日上班,看了一會前一天的代碼,做了結論:今天估計要接著撞墻,于是繼續。
接近中午,正撞得過癮,突然,一同事失手掉落茶杯,清脆的聲音和散落的碎片一下轉移了我的注意力。對,就是
打碎!腦子里的燈泡一亮(呵呵,此處純屬蒙太奇效果)。打碎不就行了嗎?
在手機端將一個字符串按UTF-8打成字節數組,傳到服務器端,然后在服務器端將同樣的字符串按UTF-8打成字節數
組,兩者比較找差別。
比如:在手機端將“中文測試”按UTF-8打成字節數組,在服務器上也將“中文測試”按UTF-8打成字節數組,兩者
肯定不同,因為一樣的話就不存在亂碼問題了。
經過在多種情況下(中文,英文,數字,特殊符號)對比兩個字節數組,發現如下不同:
中文或特殊字符(不在ASCII范圍內): j2me端的字節數組與服務器端.net環境下的字節數組,每一個字節都相差25
6。 英文或數字(在ASCII范圍內): 一個字符就是一個字節, j2me端與.net服務器端值一樣。
規律出來了,剩下的事情就是砍瓜切菜,想怎么來就怎么來:
終端在發送前,將待發送字符串中的字符挨個取出,按UTF-8打成字節數組,當字節數組的長度大于一時,當前字
符即為漢字或特殊字符,則每個字節的值不變;如果字符被打成字節數組的長度等于一,則為ASCII范圍內字符,字
節值減去256。
.netWEB服務端:將接收到的字節數組,挨個增加256,然后按“UTF-8”組成字符串即可。
奮戰到12點半,終于完成了編寫,測試:我在終端傳進“帥哥”,服務端數據庫里新增記錄顯示“lostsky_11”,BINGAL
O!亂碼問題解決!(呵呵 別倒!其實是傳入“我愛北京天安門”,數據庫里也如實記錄,沒有亂碼)
解決了問題,回頭就該追究原因了,分析如下:
1,java里的byte范圍為-128~127, .net中byte的范圍為0~255;
2,utf-8處理ASCII范圍內字符用一個字節表示,中文等時用大于一個字節表示,造成“字符不等長”。
在習慣了調用現成方法編碼解碼之后,面對突然變化的情況,人很容易被慣性推進迷茫。只有 退,思,辨才能洞見本質,細微處入手,所謂“以無間入有間”。
群木難舟 一葦渡江 善哉