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 conversiondo {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%27aout.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);}

Android:URLEncoder空格被转码为“+”号相关推荐

  1. Android -- 带你从源码角度领悟Dagger2入门到放弃(一)

    1,以前的博客也写了两篇关于Dagger2,但是感觉自己使用的时候还是云里雾里的,更不谈各位来看博客的同学了,所以今天打算和大家再一次的入坑试试,最后一次了,保证最后一次了. 2,接入项目 在项目的G ...

  2. <漫漫Android路>AOSP源码获取编译及问题处理

    漫漫Android路---1.AOSP源码获取编译及导入 写在前面 环境准备 AOSP源码获取 1.Repo下载配置 2.Git安装及配置 3.AOSP获取 AOSP源码编译 1.安装编译依赖 2.开 ...

  3. Android 基于Zxing的扫码功能实现(二)

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 引言 本篇博文是基于 Android 二维码的扫码功能实现(一) 文章写的,建议阅读这篇文章之前,先看看上篇文章.还有建议阅读本文的 ...

  4. Android WIFI调试助手源码分析

    **WIFI调试助手源码(支持十六进制和ACSII发送与接收) 客户端(我自己修改的工程文件,支持十六制的接收与发送,主要是通信协议,代码简单,可轻松改造为上位机) ** 分为操作分析和代码分析. 1 ...

  5. Android上百实例源码分析以及开源分析集合打包

    感谢网友banketree的收集,压缩包的内容如下: 1.360新版特性界面源代码 实现了360新版特性界面的效果,主要涉及到Qt的一些事件处理与自定义控件.但源码好像是c++. 2.aidl跨进程调 ...

  6. Android 8.0系统源码分析--Camera processCaptureResult结果回传源码分析

    相机,从上到下概览一下,真是太大了,上面的APP->Framework->CameraServer->CameraHAL,HAL进程中Pipeline.接各种算法的Node.再往下的 ...

  7. linux 音频播放器源码,Android音乐播放器源码

    相当完整的Android音乐播放器,直接上效果图及源代码,自己欣赏,具体不再解释了,可以说是一个很给力的Android音乐播放器. 示例代码: /* * Copyright (C) 2009 Tele ...

  8. Android AOSP基础(四)Source Insight和Android Studio导入系统源码

    本文首发于微信公众号「刘望舒」 关联系列 Android AOSP基础系列 Android系统启动系列 前言 在上一篇文章Android AOSP基础(三)Android系统源码的整编和单编中,我们对 ...

  9. Android平台下二维码漏洞攻击杂谈

    路人甲 · 2015/12/02 12:42 0x00 前言 现在Android App几乎都有二维码扫描功能,如果没有考虑到二维码可能存在的安全问题,将会导致扫描二维码就会受到漏洞攻击,严重的可能导 ...

最新文章

  1. 百度AI开放平台3.0:平等赋能成为百度AI关键词
  2. 1.解决python中导入包不成功的问题(出现CondaHTTPError: HTTP 000 CONNECTION FAILED for url问题)
  3. 从架构特点到功能缺陷,重新认识分析型分布式数据库
  4. Xampp安装PHPUnit
  5. javascript高级程序设计pdf_一个老牌程序员推荐的JavaScript的书籍,看了真的不后悔!...
  6. 功能对等四个原则_佛山房屋加固工程需遵循的原则与步骤
  7. 《Apache SkyWalking实战》送书活动结果公布
  8. std::reserves使用
  9. Spring入门(四):使用Maven管理Spring项目
  10. 使用javascript的“委托”实现attachEvent
  11. 微信小程序轮播图点击跳转页面
  12. python获取上周一的日期
  13. 物联网--ESP32开发笔记(2) domoticz mqtt的一些坑的记录
  14. Ubuntu LTS 18.04 双硬盘双系统安装以个人优化
  15. Jsp实现Javaweb页面
  16. 手撕设计模式,如何理解依赖倒置原则和好莱坞原则
  17. 项目部署-didi/LogiKM
  18. Linux内核源代码获取教程
  19. 色素疤痕应该如何修复?(色素沉着疤痕怎么修复)
  20. java 画爱心壮那首歌最,抖音貂蝉大招画爱心的背景音乐是什么

热门文章

  1. matlab机器人雅可比矩阵实验,机械臂通过雅可比矩阵实现正运动学及逆运动学迭代解(工具:matlab)...
  2. Mir2Ei Avi播放修复
  3. 磁盘碎片管理Diskeeper或V-locity
  4. 【基础知识】电阻标称阻值查询表
  5. 怎么在电脑上打开epub格式电子书
  6. 中国十大免费电影网站排行
  7. 树莓派 9 周年:你不知道的树莓派冷知识
  8. 地平线正式落户上海临港 政企合作推动城市智能化发展
  9. JDK8新特性-Map遍历比较
  10. 基于OpenCV的刷脸考勤&人脸校验&用户管理系统(源码&教程)