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~
共有 0 条评论