软件编程
位置:首页>> 软件编程>> Android编程>> Android中URLEncoder空格被转码为"+"号的处理办法

Android中URLEncoder空格被转码为"+"号的处理办法

作者:bdmh  发布时间:2022-02-09 17:58:12 

标签:urlencoder,空格,转码

Android前段和后端接口进行交互时,经常会遇到特殊字符,比如表情、特殊标点等,这样在Url中是无法识别的,需要进行转码,后端进行解码交互。

但当使用URLEncoder时,会发现字符串中的空格被转换成“+”号,如果编码后的内容入库后,将导致读取时,前段本来是空格的地方,会显示成“+”号字符。

Android中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);
}

我们讨论的问题,就是下面这几行。

Android中URLEncoder空格被转码为"+"号的处理办法

那么如何处理该问题呢?

注意:网上那种替换空格或加号的方法是不可行的,因为可能会替换掉正常的空格和加号。

建议自己仿照官方的代码,写一套自己转码和解码过程,这个不难的。或者找第三方的(比如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

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com