Android中URLEncoder空格被转码为"+"号的处理办法
作者:bdmh 发布时间:2022-02-09 17:58:12
标签:urlencoder,空格,转码
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


猜你喜欢
- 本篇随笔将讲解一下Android当中比较常用的两个布局容器--ScrollView和HorizontalScrollView,从字面意义上来
- 我就废话不多说了,大家还是直接看代码吧~ public List<FreightM> sortList(List&l
- 本文为大家分享了JSplitPane的使用方法,供大家参考,具体内容如下1、swing分割窗口控件JSplitPane,用来将窗口分割成两个
- 概念CAS的全称是Compare-And-Swap,它是cpu并发原语它的功能是判断内存某个位置的值是否为预期值。如果是则更改为新的值,这个
- 本文实例为大家分享了C语言实现两个矩阵相乘的具体代码,供大家参考,具体内容如下程序功能:实现两个矩阵相乘的C语言程序,并将其输出代码如下:#
- 1.简介if判断语句是很多编程语言的重要组成部分。但是,若我们最终编写了大量嵌套的if语句,这将使得我们的代码更加复杂和难以维护。让我们看看
- 第一篇是纯利用现有JDK提供的绘图类(ImageIO)类制作,这个过程比较复杂且需要了解ImageIO类。这一篇文章是利用Hutool工具类
- 微信公众号,仿照企业号的思路,增加了标签管理的功能,对关注的粉丝可以设置标签管理,实现更加方便的分组管理功能。开发者可以使用用户标签管理的相
- 一. 为什么要使用接口假如有一个需求:要求实现防盗门的功能。门有"开"和"关"的功能,锁有"
- 本文实例讲述了android从资源文件中读取文件流并显示的方法。分享给大家供大家参考。具体如下:在android中,假如有的文本文件,比如T
- 五子棋游戏(Java),供大家参考,具体内容如下思路:1.首先创建一个棋盘,建立一个二维数组,此文中为一个15*15的二维数组,2.初始化棋
- 本文实例为大家分享了winform循环播放多个视频的具体代码,供大家参考,具体内容如下环境: vs2015 +winform首先,vs自带组
- 面向过程和面向对象的区别面向过程:当事件比较简单的时候,利用面向过程,注重的是事件的具体步骤和过程,注重的是过程中的具体行为,以函数为最小单
- 解决项目中表单重复提交的问题,在平常的项目中有以下几种可能出现表单重复提交的情况,比如说:1.由于服务器缓慢或者网络延迟的原因,重复点击提交
- spring 多文件配置:1、properties文件2、YAML文件一、properties文件在 Spring Boot 中, 多环境配
- 介绍Dubbo 是一款高性能、轻量级的 Java RPC 框架,由阿里巴巴开源并贡献至 Apache 基金会。它能够提供服务的注册与发现、负
- 刚毕业的第一份工作是 java 开发,项目中需要用到 mybatis,特此记录学习过程,这只是一个简单 demo,mybatis 用法很多不
- Class.forName(xxx.xx.xx) 返回的是一个类一.首先你要明白在java里面任何class都要装载在虚拟机上才能运行。1.
- 学习过java基础,最近趁着大量课余时间想学习Android开发。百度很多资料Android studio,由Google开发的开发工具,那
- 前言本文主要介绍JWT的实战运用。准备工作首先我们创建一个Asp.Net的,包含MVC和WebApi的Web项目。然后使用Nuget搜索JW