URL中关于空格的编码转换成+或转换成%20的问题

本人Android开发,某一天,被告知自己程序URL的编码中,空格被转换成了+,导致对方识别不成空格。当然我清楚的记得我是使用了URLEncoder的编码和解码方法,并无其他操作,而且这可是JDK提供的方法,因此我直接进行了测试
URLEncoder.encode("张三 妈妈","UTF-8")
其输出结果为:%E5%BC%A0%E4%B8%89+%E5%A6%88%E5%A6%88
跟上面描述的现象一致,按道理这里我门需要这个空格转换成是%20才对
因此我尝试了另外一个方法:Uri.encode("张三 妈妈")
Uri是Android SDK提供的方法,其输出结果为:%E5%BC%A0%E4%B8%89%20%E5%A6%88%E5%A6%88
这就是我们预期的结果了。
但是如果不是Android开发,没有Uri这个类的支持该怎么办呢,查资料有人的做法是URLEncoder之后,替换所有的+为%20,然后在URLDecoder,因为URLDecoder可以将+和%20转换成空格。

后来我尝试了很多在线的URL转换工具,有些将空格转换成了+有些转换成了 %20,当然直觉告诉我肯定不是谁对谁错,肯定是标准不同或采用的语言差异等导致的,以下是引用别人的介绍:http://blog.csdn.net/foxpeter/article/details/23475293

一个URL的基本组成部分包括协议(scheme),域名,端口号,路径和查询字符串(路径参数和锚点标记就暂不考虑了)。路径和查询字符串之间用问号?分离。例如http://www.example.com/index?param=1,路径为index,查询字符串(Query String)为param=1。URL中关于空格的编码正是与空格所在位置相关:空格被编码成加号+的情况只会在查询字符串部分出现,而被编码成%20则可以出现在路径和查询字符串中。
造成这种混乱局面的原因在于:W3C标准规定,当Content-Type为application/x-www-form-urlencoded时,URL中查询参数名和参数值中空格要用加号+替代,所以几乎所有使用该规范的浏览器在表单提交后,URL查询参数中空格都会被编成加号+。而在另一份规范(RFC 2396,定义URI)里, URI里的保留字符都需转义成%HH格式(Section 3.4 Query Component),因此空格会被编码成%20,加号+本身也作为保留字而被编成%2B,对于某些遵循RFC 2396标准的应用来说,它可能不接受查询字符串中出现加号+,认为它是非法字符。所以一个安全的举措是URL中统一使用%20来编码空格字符。
Java中的URLEncoder本意是用来把字符串编码成application/x-www-form-urlencoded MIME格式字符串,也就是说仅仅适用于URL中的查询字符串部分,但是URLEncoder经常被用来对URL的其他部分编码,它的encode方法会把空格编成加号+,与之对应的是,URLDecoder的decode方法会把加号+和%20都解码为空格,这种违反直觉的做法造成了当初我对空格URL编码问题的困扰。因此后来我的做法都是,在调用URLEncoder.encode对URL进行编码后(所有加号+已被编码成%2B),再调用replaceAll(“\+”, “%20″),将所有加号+替换为%20。

推荐阅读更多精彩内容