在和web服务进行交互时,我们经常需要对URL中的特定字符和传输的表单数据进行百分号编码。例如,’&’在百分号编码时会变成’%26’。搞清楚 URL中哪部分的哪些字符应该进行百分号编码了并不是件易事。最好的资料好像是RFC 3986和W3C HTML5。出于兴趣和教育目的,我创建了swift的String的扩展(和作为对比的Objective-C的分类)。

RFC3986 编码查询字符串

在 RFC3986 的第2.3节列出了你不需要百分号编码的字符,因为它们在URL中没有特殊的含义。

ALPHA / DIGIT / “-” / “.” / “_” / “~”

α/数字/”-”/”.”/”_”

第3.4节也解释了因为查询往往会本身包含一个URL,最好不要百分号编码斜杠(“/”)和问号(“?”)。这也是受欢迎的iOS HTTP网络库Alamofire采取的方法,这给了我信心。

因此,用RFC 3986编码一个兼容性的查询,我们可以百分号编码如上所述以外的所有字符。这很简单,如果我们首先构建一组允许的字符,然后用stringByAddingPercentEncodingWithAllowedCharacters去编码剩余的。

注意:苹果已经在iOS 9中弃用了stringByAddingPercentEscapesUsingEncoding或CFURLCreateStringByAddingPercentEscapes这两个方法。

Swift

首先,swift String extension:extension String {

func stringByAddingPercentEncodingForRFC3986() -> String? {

let unreserved = "-._~/?"

let allowed = NSMutableCharacterSet.alphanumericCharacterSet()

allowed.addCharactersInString(unreserved)

return stringByAddingPercentEncodingWithAllowedCharacters(allowed)

}

}

Object-C

我们可以用Object-C的NSString的分类来做相同的事。@implementation NSString (URLEncoding)

- (nullable NSString *)stringByAddingPercentEncodingForRFC3986 {

NSString *unreserved = @"-._~/?";

NSMutableCharacterSet *allowed = [NSMutableCharacterSet alphanumericCharacterSet];

[allowed addCharactersInString:unreserved];

return [self stringByAddingPercentEncodingWithAllowedCharacters: allowed];

}

@end

用例// Swift

let query = "one&two =three"

let encoded = query.stringByAddingPercentEncodingForRFC3986()

// "one%26two%20%3Dthree"

// Objective-C

NSString *query = @"one&two =three";

NSString *encoded = [query stringByAddingPercentEncodingForRFC3986];

// "one%26two%20%3Dthree"

对x-www-form-urlencoded进行编码

推荐W3C HTML5 对表单数据编码是相似的,但是和RFC 3986有一点不同。在第4.10.22.5节中告诉我们下列字符是不应该百分号编码:

ALPHA / DIGIT / “*” / “-” / “.” / “_”

α/数字/”-”/”.”/”_”

你应该用“+”(0x2B)代替空格(“ ”)。它和RFC 3986 的不同在 Stack Overflow answer 里有描述。波浪号(“~”)被百分号编码了,但是星号(“*”)没有。该建议很好地总结了这种情况:这种编码的表单数据在很多方面是异常的,多年来的实践的问题和折中解决导致了互通性的一系列必要操作。但是绝不代表好的设计实践。

Swift

给String extension添加一个新的方法public func stringByAddingPercentEncodingForFormData(plusForSpace: Bool=false) -> String? {

let unreserved = "*-._"

let allowed = NSMutableCharacterSet.alphanumericCharacterSet()

allowed.addCharactersInString(unreserved)

if plusForSpace {

allowed.addCharactersInString(" ")

}

var encoded = stringByAddingPercentEncodingWithAllowedCharacters(allowed)

if plusForSpace {

encoded = encoded?.stringByReplacingOccurrencesOfString(" ",

withString: "+")

}

return encoded

}

注意,由于很多 web服务好像不关心我用“+”或者百分号编码将空格做了可选的编码。

Object-C

Object-C的方法缺少一个可选参数- (nullable NSString *)stringByAddingPercentEncodingForFormData:(BOOL)plusForSpace

{

NSString *unreserved = @"*-._";

NSMutableCharacterSet *allowed = [NSMutableCharacterSet                                     alphanumericCharacterSet];

[allowed addCharactersInString:unreserved];

if (plusForSpace) {

[allowed addCharactersInString:@" "];

}

NSString *encoded = [self stringByAddingPercentEncodingWithAllowedCharacters:allowed];

if (plusForSpace) {

encoded = [encoded stringByReplacingOccurrencesOfString:@" " withString:@"+"];

}

return encoded;

}

用例:// Swift

let query = "one two"

let space = query.stringByAddingPercentEncodingForFormData()

// "one%20two"

let plus = query.stringByAddingPercentEncodingForFormData(true)

// "one+two"

// Objective-C

NSString *query = @"one two";

NSString *encodedQuery = [query stringByAddingPercentEncodingForFormData:YES];

// "one+two"

源代码

Swift代码和一些测试用例你可以在我的Github代码实例库的Encode项目里找到,Object-C的分类和测试用例在TwitterSearch项目里。欢迎反馈和改进。

深入阅读

c语言 字符串 url,如何对URL字符串进行百分号编码相关推荐

  1. nodejs处理url中的百分号编码

    nodejs处理url中的百分号编码 写网站的时候,前端表单发送数据到nodejs服务器,发送的数据会出现一些乱码,像下面这样: nickname=%E5%B0%8F%E5%88%98&gen ...

  2. 检查字符串是否为有效URL的最佳正则表达式是什么?

    如何检查给定的字符串是否是有效的URL地址? 我对正则表达式的了解是基础知识,因此我无法从网上已经看到的数百种正则表达式中进行选择. #1楼 function validateURL(textval) ...

  3. php接收get参数false是字符串,php怎么接收url参数

    php获取url中的参数信息,是PHP面试过程中常见的考点之一,也是我们日常项目开发过程中,经常需要实现的一个功能,我们可以通过PHP中parse_url等相关函数来实现. 那么对于PHP新手来说,具 ...

  4. R语言str_subset函数和str_which函数:str_subset函数提取字符串向量中所有包含匹配字符的字符串、str_which函数返回字符串向量中所有包含匹配字符的位置(索引)

    R语言str_subset函数和str_which函数:str_subset函数提取字符串向量中所有包含匹配字符的字符串.str_which函数返回字符串向量中所有包含匹配字符的位置(索引) 目录

  5. R语言stringr包str_detect函数检测字符串中模式存在与否实战

    R语言stringr包str_detect函数检测字符串中模式存在与否实战 目录 R语言stringr包str_detect函数检测字符串中模式存在与否实战 #导入stringr包

  6. R语言eval函数评估表达式或者字符串实战

    R语言eval函数评估表达式或者字符串实战 目录 R语言eval函数评估表达式或者字符串实战 #基本语法 #eval函数评估表达式

  7. Swift3.0语言教程查找字符集和子字符串

    Swift3.0语言教程查找字符集和子字符串 Swift3.0语言教程查找字符集和子字符串,在字符串中当字符内容很多时,我们就需要使用到查找字符集或者子字符串的方法.以下我们将讲解3种查找字符集和子字 ...

  8. C语言基础:时间转换成字符串 strftime的代码

    将内容过程中经常用的一些内容段做个记录,下边内容段是关于C语言基础:时间转换成字符串 strftime的内容,希望能对大伙有一些用处. #include <stdio.h> #includ ...

  9. Algorithm:C++语言实现之字符串相关算法(字符串的循环左移、字符串的全排列、带有同个字符的全排列、串匹配问题的BF算法和KMP算法)

    Algorithm:C++语言实现之字符串相关算法(字符串的循环左移.字符串的全排列.带有同个字符的全排列.串匹配问题的BF算法和KMP算法) 目录 一.字符串的算法 1.字符串的循环左移 2.字符串 ...

最新文章

  1. Kafka入门教程与详解
  2. Annu. Rev. Genet:植物微生物组——系统性见解与展望
  3. 英伟达公开课 | 如何突破Decoder性能瓶颈?揭秘FasterTransformer2.0的原理与应用,已开源...
  4. php判断是否已关注,php判断用户是否关注微信订阅号或公众号
  5. python列表中包含元祖_python列表与元祖
  6. 从蚂蚁金服一窥人工智能在金融领域的机遇与挑战
  7. 20210928 对角化的充要条件
  8. GitHub发布桌面版但不包括Linux
  9. iphone桌面横屏设置在哪里_我和我各司其职的桌面们
  10. php找不到phpmyadmin,phpMyAdmin 安装配置方法和问题解决
  11. Win10+Torch1.9+CUDA11.1成功配置YOLOX预测环境
  12. c++知识整理 编程模块
  13. 分享97个上传下载PHP源码,总有一款适合你
  14. Terminal终端命令(全)
  15. 功率半导体器件的研究意义
  16. Chrome插件(扩展)开发全攻略
  17. android视频播放异常,Android 播放视频常见问题小结
  18. oracle连接超时是什么意思,oracle连接超时自动断开问题
  19. R语言如何从外部读取数据到R中
  20. 已解决org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML异

热门文章

  1. Django—路由层,视图层
  2. Homebrew是什么?怎么关闭自动更新?
  3. burpsuite破解版
  4. 需加装饰——装饰模式
  5. ASP.NET Web API 数据提供系统相关类型及其关系
  6. POJ 1222 1681 1830 3185 开关灯问题 (高斯消元 异或方程组)
  7. ashly理器4.8软件汉化版_AMD 处理器核心比英特尔多还更便宜?英特尔回应
  8. 三星 原生android,原生Android 4.0 三星GALAXY Nexus评测
  9. java线程统一_Java线程结果不一致
  10. c语言用星号输出沙漏,《算法笔记》学习日记——3.3 图形输出