Android中URLEncoder空格被轉(zhuǎn)碼為"+"號(hào)的處理辦法
Android前段和后端接口進(jìn)行交互時(shí),經(jīng)常會(huì)遇到特殊字符,比如表情、特殊標(biāo)點(diǎn)等,這樣在Url中是無法識(shí)別的,需要進(jìn)行轉(zhuǎn)碼,后端進(jìn)行解碼交互。
但當(dāng)使用URLEncoder時(shí),會(huì)發(fā)現(xiàn)字符串中的空格被轉(zhuǎn)換成“+”號(hào),如果編碼后的內(nèi)容入庫后,將導(dǎo)致讀取時(shí),前段本來是空格的地方,會(huì)顯示成“+”號(hào)字符。
到底為什么會(huì)這樣,我們還是看看源碼的實(shí)現(xiàn)。
首選,URLEncoder中定義了哪些字符不可以被轉(zhuǎn)碼。
static BitSet dontNeedEncoding;
dontNeedEncoding中就包含了不允許轉(zhuǎn)碼的字符集合,只有在這里面能找不到的字符才會(huì)被正常轉(zhuǎn)碼。下面是dontNeedEncoding初始化過程
static { //創(chuàng)建一個(gè)容量為256的位集合 dontNeedEncoding = new BitSet(256); int i; //循環(huán)a-z,將其字符值(不是字符串值)存入 for (i = 'a'; i <= 'z'; i++) { dontNeedEncoding.set(i); } //同上 for (i = 'A'; i <= 'Z'; i++) { dontNeedEncoding.set(i); } //同上 for (i = '0'; i <= '9'; i++) { dontNeedEncoding.set(i); } //在這個(gè)地方,官方特意做了說明 //空格將被編碼為加號(hào) dontNeedEncoding.set(' '); /* encoding a space to a + is done * in the encode() method */ dontNeedEncoding.set('-'); dontNeedEncoding.set('_'); dontNeedEncoding.set('.'); dontNeedEncoding.set('*'); //默認(rèn)編碼格式 dfltEncName = AccessController.doPrivileged( new GetPropertyAction("file.encoding") ); }
上面的代碼我們看到,除了英文字母,數(shù)字和幾個(gè)能識(shí)別的字符外,都需要轉(zhuǎn)碼。
我們再來看看encode方法。
public static String encode(String s, String enc) throws UnsupportedEncodingException { //標(biāo)記是否有字符被轉(zhuǎn)碼了,如果沒有,就直接返回原始字符串 //如果有,就返回out的結(jié)果 boolean needToChange = false; //存放轉(zhuǎn)碼后的結(jié)果 StringBuffer out = new StringBuffer(s.length()); Charset charset; CharArrayWriter charArrayWriter = new CharArrayWriter(); //如果未指定編碼,拋出異常 if (enc == null) throw new NullPointerException("charsetName"); try { charset = Charset.forName(enc); } catch (IllegalCharsetNameException e) { throw new UnsupportedEncodingException(enc); } catch (UnsupportedCharsetException e) { throw new UnsupportedEncodingException(enc); } //遍歷要編碼的字符串 for (int i = 0; i < s.length();) { //取出指定位置的字符 int c = (int) s.charAt(i); if (dontNeedEncoding.get(c)) { //這里,判斷如果字符是空格,就轉(zhuǎn)為“+” if (c == ' ') { c = '+'; needToChange = true; } out.append((char)c); i++; } else { // convert to external encoding before hex conversion do { charArrayWriter.write(c); /* * 下面就是轉(zhuǎn)碼unicode相關(guān)代碼 */ if (c >= 0xD800 && c <= 0xDBFF) { ...... } i++; } while (i < s.length() && !dontNeedEncoding.get((c = (int) s.charAt(i)))); charArrayWriter.flush(); String str = new String(charArrayWriter.toCharArray()); byte[] ba = str.getBytes(charset); for (int j = 0; j < ba.length; j++) { //添加百分號(hào),比如a'a轉(zhuǎn)為a%27a out.append('%'); ...... } charArrayWriter.reset(); needToChange = true; } } return (needToChange? out.toString() : s); }
我們討論的問題,就是下面這幾行。
那么如何處理該問題呢?
注意:網(wǎng)上那種替換空格或加號(hào)的方法是不可行的,因?yàn)榭赡軙?huì)替換掉正常的空格和加號(hào)。
建議自己仿照官方的代碼,寫一套自己轉(zhuǎn)碼和解碼過程,這個(gè)不難的?;蛘哒业谌降模ū热鐂pring提供的 UriUtils
)。
另外,Android提供了Uri.encode,雖然可以正常轉(zhuǎn)碼空格,但是它不需要轉(zhuǎn)換的字符和URLEncode有一點(diǎn)差別,大家在用的時(shí)候,根據(jù)情況選擇即可。
下面是Uri.encode中不會(huì)被轉(zhuǎn)碼的字符
/** * Returns true if the given character is allowed. * * @param c character to check * @param allow characters to allow * @return true if the character is allowed or false if it should be * encoded */ private static boolean isAllowed(char c, String allow) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || "_-!.~'()*".indexOf(c) != NOT_FOUND || (allow != null && allow.indexOf(c) != NOT_FOUND); }
總結(jié)
到此這篇關(guān)于Android中URLEncoder空格被轉(zhuǎn)碼為"+"號(hào)的處理辦法的文章就介紹到這了,更多相關(guān)Android URLEncoder空格被轉(zhuǎn)碼+號(hào)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android 中FloatingActionButton(懸浮按鈕)實(shí)例詳解
這篇文章主要介紹了Android 中FloatingActionButton(懸浮按鈕)實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-05-05Android實(shí)現(xiàn)桌面懸浮窗、蒙板效果實(shí)例代碼
這篇文章主要介紹了Android實(shí)現(xiàn)桌面懸浮窗、蒙板效果實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-05-05基于Retrofit2+RxJava2實(shí)現(xiàn)Android App自動(dòng)更新
這篇文章主要為大家詳細(xì)介紹了基于Retrofit2+RxJava2實(shí)現(xiàn)Android App自動(dòng)更新,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05Android UI實(shí)現(xiàn)底部切換標(biāo)簽fragment
這篇文章主要為大家詳細(xì)介紹了Android UI實(shí)現(xiàn)底部切換標(biāo)簽的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12超精準(zhǔn)的Android手機(jī)計(jì)步器開發(fā)
這篇文章主要為大家詳細(xì)介紹了超精準(zhǔn)的Android手機(jī)計(jì)步器開發(fā)過程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10android計(jì)算器簡單實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了android計(jì)算器的簡單實(shí)現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03使用User Agent分辨出Android設(shè)備類型的安全做法
這篇文章主要介紹了使用User Agent分辨出Android設(shè)備類型的安全做法,本文得出的結(jié)論是當(dāng)你依據(jù)檢測UA來判斷Android手機(jī)設(shè)備,請同時(shí)檢查android和mobile兩個(gè)字符串,需要的朋友可以參考下2015-01-01Android獲取所在時(shí)區(qū)時(shí)間的兩種方式
Android獲取所在時(shí)區(qū)正確時(shí)間的方式有兩種,通過wifi獲取時(shí)間和通過通過GPS獲取時(shí)間這兩種方式,文中通過代碼示例給大家的介紹的非常詳細(xì),需要的朋友可以參考下2024-04-04Android實(shí)現(xiàn)3D翻轉(zhuǎn)動(dòng)畫效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)3D翻轉(zhuǎn)動(dòng)畫效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12Android OkHttp實(shí)現(xiàn)全局過期token自動(dòng)刷新示例
本篇文章主要介紹了Android OkHttp實(shí)現(xiàn)全局過期token自動(dòng)刷新示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03