URL详解以及iOS中URLencode和URLdecode

URI和URL

URI

统一资源标志符(英语:Uniform Resource Identifier,缩写:URI)在计算机术语中是用于标志某一互联网资源名称的字符串。

URL

统一资源定位符(英语:Uniform Resource Locator,缩写:URL,或称统一资源定位器、定位地址、URL地址俗称网页地址,简称网址,是因特网上标准的资源的地址(Address),如同在网络上的门牌。

URN

统一资源名称(英语:Uniform Resource Name,缩写:URN)是统一资源标识(URI)的历史名字。

URI定义这么一个资源,这个资源可以通过唯一的名称(URN)表示,也可以通过唯一的地址(URL)表示。

目前网络上的资源基本都是URL表示形式,平常所说的URI基本都是URL了。

URL的组成

通用的URL组成如下,非必需

scheme://user:password@host:port/path/data?key=value&key1=value1#fragment
scheme: 协议部分,常见的有: http,https,mailto,ftp,rtsp,rtspu,file。
user:password 用户名+密码
host 域名,也可以是IP
port 端口号,非必需,如果省略就是默认端口。
path 虚拟路径,从第一个/开始到最后一个/结束,/path/data这部分都是虚拟路径,data如果省略就是默认文件
query 参数或查询字符串,? 到#中间的部分,非必需
fragment 片段。

可以看出URL中是包含一些特殊字符的,如果不对这些字符如果参数路径中包含这些这些字符,就会产生歧义。

关于URL编码和解码

为什么要编码和解码,就是要处理URL中的特殊字符,网络标准RFC 1738做了硬性规定:

"...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*'()," [not including the quotes - ed], and reserved characters used for their reserved purposes may be used unencoded within a URL."

"只有字母和数字[0-9a-zA-Z]、一些特殊符号"$-_.+!*'(),"[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL。"

RFC 3986 保留字符:

! * ' ( ) ; : @ & = + $ , / ? # [ ]

RFC 3986 未保留字符:A-Z,a-z,0-9,- _ . ~

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r s t u v w x y z
0 1 2 3 4 5 6 7 8 9 - _ . ~

以上的字符,可以不经过编码,直接用于URL

编码和解码

URL encoding是Uniform Resource Identifier(URI)规范文档中对特殊字符编码制定的规则。本质是把一个字符转为 %加上UTF-8编码对应的16进制数字。故又称之为Percent-encoding。

iOS 中URL encode的方式

已经弃用的方式

NSString *encode = [orgStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];//编码
NSString *decode = [encode stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];//解码

由于 RFC中规定的字符会随着版本的发生细微的变化,所以stringByAddingPercentEscapesUsingEncoding已被弃用,取而代之的是NSCharacterSet,可以自定义NSCharacterSet中的字符。

目前苹果推荐的编码解码方式

NSCharacterSet *encodeSet = [NSCharacterSet characterSetWithCharactersInString:@"!*'();:@&=+$,/?%#[]"];
NSString *encode = [encode stringByAddingPercentEncodingWithAllowedCharacters:encodeSet];//编码
NSString *decode = [encode stringByRemovingPercentEncoding];//解码

或者CoreFoundation下的

 // 编码
NSString *encodedString = (NSString *)
     CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                              (CFStringRef)self,
                                                               NULL,
                                                              (CFStringRef)@"!*'();:@&=+$,/?%#[]",
                                                               kCFStringEncodingUTF8));
 //解码
NSString *decoded = (__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (CFStringRef)self, CFSTR(""), kCFStringEncodingUTF8);

NSCharacterSet

NSCharacterSet对象表示一组Unicode字符,但和NSSet没任何关系,因此不能以集合的方式遍历NSCharacterSet字符集:

以下代码可以显示NSCharacterSet对象中的所有字符。

原理:OC中的字符是Unicode字符集(Swift也是)Unicode共有17个扇区,每个扇区能表示65535个Unicode字符,用4个字节就可以表示任意Unicode码点,通过遍历Unicode字符集就可以找出NSCharacterSet包含的集合了;
hasMemberInPlane:判断当前字符是否在当前扇区。
longCharacterIsMember:当前字符在字符集中是否存在。

以下是遍历NSCharacterSet字符集一种的实现方式。

NSString* characters(NSCharacterSet *set){
    NSMutableString *string = [NSMutableString string];
    for (UInt8 plane = 0; plane < 17; plane++) {
        if ([set hasMemberInPlane:plane]){
            UInt32 p0 = (UInt32)plane * 65535;
            UInt32 p1 = (UInt32)(plane + 1) * 65535;
            for (UInt32 i = p0; i < p1; i ++) {
                if([set longCharacterIsMember:i]){
                    [string appendFormat:@"%c",I];
                }
            }
        }
    }
    return string;
 }

自定义集合,验证实现:

NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@",.;'[]=-09kj"];
characters(set);

打印结果:

',-.09;=[]jk

NSCharacterSet提供了标准字符集:部分字符集遍历结果如下:
URLUserAllowedCharacterSet

!$&'()*+,-.0123456789;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~

URLHostAllowedCharacterSet

!$&'()*+,-.0123456789:;=ABCDEFGHIJKLMNOPQRSTUVWXYZ[]_abcdefghijklmnopqrstuvwxyz~

URLQueryAllowedCharacterSet

!$&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~

URLPathAllowedCharacterSet

!$&'()*+,-./0123456789:=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~

URLPasswordAllowedCharacterSet

!$&'()*+,-.0123456789;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~

URLFragmentAllowedCharacterSet

!$&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容