網站首頁 編程語言 正文
Android前段和后端接口進行交互時,經常會遇到特殊字符,比如表情、特殊標點等,這樣在Url中是無法識別的,需要進行轉碼,后端進行解碼交互。
但當使用URLEncoder時,會發現字符串中的空格被轉換成“+”號,如果編碼后的內容入庫后,將導致讀取時,前段本來是空格的地方,會顯示成“+”號字符。
到底為什么會這樣,我們還是看看源碼的實現。
首選,URLEncoder中定義了哪些字符不可以被轉碼。
static BitSet dontNeedEncoding;
dontNeedEncoding中就包含了不允許轉碼的字符集合,只有在這里面能找不到的字符才會被正常轉碼。下面是dontNeedEncoding初始化過程
static { //創建一個容量為256的位集合 dontNeedEncoding = new BitSet(256); int i; //循環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); } //在這個地方,官方特意做了說明 //空格將被編碼為加號 dontNeedEncoding.set(' '); /* encoding a space to a + is done * in the encode() method */ dontNeedEncoding.set('-'); dontNeedEncoding.set('_'); dontNeedEncoding.set('.'); dontNeedEncoding.set('*'); //默認編碼格式 dfltEncName = AccessController.doPrivileged( new GetPropertyAction("file.encoding") ); }
上面的代碼我們看到,除了英文字母,數字和幾個能識別的字符外,都需要轉碼。
我們再來看看encode方法。
public static String encode(String s, String enc) throws UnsupportedEncodingException { //標記是否有字符被轉碼了,如果沒有,就直接返回原始字符串 //如果有,就返回out的結果 boolean needToChange = false; //存放轉碼后的結果 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)) { //這里,判斷如果字符是空格,就轉為“+” if (c == ' ') { c = '+'; needToChange = true; } out.append((char)c); i++; } else { // convert to external encoding before hex conversion do { charArrayWriter.write(c); /* * 下面就是轉碼unicode相關代碼 */ 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++) { //添加百分號,比如a'a轉為a%27a out.append('%'); ...... } charArrayWriter.reset(); needToChange = true; } } return (needToChange? out.toString() : s); }
我們討論的問題,就是下面這幾行。
那么如何處理該問題呢?
注意:網上那種替換空格或加號的方法是不可行的,因為可能會替換掉正常的空格和加號。
建議自己仿照官方的代碼,寫一套自己轉碼和解碼過程,這個不難的。或者找第三方的(比如spring提供的?UriUtils
?)。
另外,Android提供了Uri.encode,雖然可以正常轉碼空格,但是它不需要轉換的字符和URLEncode有一點差別,大家在用的時候,根據情況選擇即可。
下面是Uri.encode中不會被轉碼的字符
/** * 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); }
總結
原文鏈接:https://blog.csdn.net/bdmh/article/details/128608795
相關推薦
- 2022-07-13 常用類之包裝類和String類
- 2023-12-15 log4j.properties自定義日志配置
- 2023-06-13 react實現組件狀態緩存的示例代碼_React
- 2023-05-12 Python時間戳轉換為字符串與字符串轉換為時間戳_python
- 2022-07-09 Android開發Dart?Constructors構造函數使用技巧整理_Android
- 2022-09-09 pycharm?如何縮進和SQL亂碼及SQL包含變量_python
- 2022-05-24 調用無文檔說明的?Web?API過程描述_相關技巧
- 2022-09-05 Golang中的Interface詳解_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支