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~

你可能感兴趣的:(URL详解以及iOS中URLencode和URLdecode)