Objective C URL编码转换

本文出自 清风徐来,水波不兴 的博客,转载时请注明出处及相应链接。

本文永久链接: http://www.winddisk.com/2012/05/26/objective_c_url_encode/

一.URL编码

URL串只能包含限制性的少数字符。根据RFC2396的定义,允许在URL中出现的字符分为保留字符和非保留字符。

  • 保留字符:
    reserved = “;” | “/” | “?” | “:” | “@” | “&” | “=” | “+” | “$” | “,”
    保留字符主要用于分隔URL的各个部分。
  • 非保留字符:
    unreserved = alphanum | mark
    mark = “-” | “_” | “.” | “!” | “~” | “*” | “‘” | “(” | “)”
    非保留字符包含大小写的英文字母,数字,以及mark中的符号。

除这些字符以外的其他字符如果要出现在URL中,需要进行编码,编码的格式为escaped = “%” hex hex,即“%”号后接两个16进制数字,编码中的数字为该字符的二进制表示。例如空格编码后的表示为%20,”~”编码后的表示为%7E,中文“相”的编码表示为%E7%9B%B8。

保留的字符用于分隔URL组件时不需编码,当其本身为数据,即为组件的一部分时也需要进行编码,同样”%”本身作为数据时也需要进行编码。

RFC3986对URL语法进行了更新,对URL中可以出现的字符也进行了更新:

  • 保留字符:
    reserved = gen-delims / sub-delims
    gen-delims = “:” / “/” / “?” / “#” / “[" / "]” / “@”
    sub-delims = “!” / “$” / “&” / “‘” / “(” / “)” / “*” / “+” / “,” / “;” / “=”
  • 非保留字符:
    unreserved = alphanum | mark
    mark = “-” | “_” | “.” | “!” | “~” | “*” | “‘” | “(” | “)”

与RFC2396相比,非保留字符没有变化,保留字符分为了两类gen-delims,sub-delims,其中增加了三个保留字符”#” / “[" / "]“。

gen-delims用于分隔各个组件,sub-delims用于分隔组件内部的数据。例如http://www.winddisk.com/wp-admin/post.php?post=999&action=edit。gen-delims中的”:”分隔协议与主机,”/”分隔主机与路径,“?”分隔主机和查询参数。sub-delims中的”&”用于分隔查询参数中的键值对,”=”用于分隔键值对中的键和值。

二.NSString URL编码方法

NSString的stringByAddingPercentEscapesUsingEncoding:方法可将普通字符串进行编码生成URL字符串,其会将所有不允许出现的URL中的字符进行转义编码。经测试,其根据的是RFC2396协议,因为其对RFC3986新增的保留字符”#” / “[" / "]“也进行了编码。

NSString* RFC3986String = @"azAZ09-._~:/?#[]@!$&'()*+,;=";
NSString* RFC2396String = @"azAZ09-_.!~*'();/?:@&=+$,";

NSString* RFC3986Url = [RFC3986String stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString* RFC2396Url = [RFC2396String stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

NSLog(@"RFC3986Str:%@",RFC3986String);
NSLog(@"RFC3986Url:%@",RFC3986Url);
NSLog(@"RFC2396Str:%@",RFC2396String);
NSLog(@"FFC2396Url:%@",RFC2396Url);

其输出结果为

RFC3986Str: azAZ09-._~:/?#[]@!$&'()*+,;=
RFC3986Url: azAZ09-._~:/?%23%5B%5D@!$&'()*+,;=
RFC2396Str: azAZ09-_.!~*'();/?:@&=+$,
FFC2396Url: azAZ09-_.!~*'();/?:@&=+$,

可见,对字符”#” / “[" / "]“也进行了编码。

stringByAddingPercentEscapesUsingEncoding 对应的解码方法为stringByReplacingPercentEscapesUsingEncoding:

三.CFURL 编码方法

为了更方便的控制对哪些字符编码,哪些字符不编码,可以使用CFURLCFURLCreateStringByAddingPercentEscapes方法,
其定义为

CFStringRef CFURLCreateStringByAddingPercentEscapes (
   CFAllocatorRef   allocator,
   CFStringRef      originalString,
   CFStringRef      charactersToLeaveUnescaped,
   CFStringRef      legalURLCharactersToBeEscaped,
   CFStringEncoding encoding
);
  • allocator为新字符串内存分配方式,可传NULL或kCFAllocatorDefault
  • originalString为原始需编码字符串;
  • charactersToLeaveUnescaped为本身为非法URL字符但不需进行编码的字符串;
  • legalURLCharactersToBeEscaped为本身为合法URL字符但需要进行编码的字符串。

那么,最后需要编码的字符为 RFC2396中定义的非法URL字符 + legalURLCharactersToBeEscaped – charactersToLeaveUnescaped.
注:苹果文档中说依据的时RFC3986,但测试发现和stringByAddingPercentEscapesUsingEncoding一样,为RFC2396.Why?

其对应的解码方法为CFURLCreateStringByReplacingPercentEscapes

CFStringRef CFURLCreateStringByReplacingPercentEscapes (
   CFAllocatorRef allocator,
   CFStringRef    originalString,
   CFStringRef    charactersToLeaveEscaped
);

示例代码:

#import "NSString+URLEncoding.h"

@implementation NSString (OAURLEncodingAdditions)

- (NSString *)URLEncodedString
{
    NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                      (CFStringRef)self, NULL,CFSTR("!*'()^;:@&=+$,/?%#[]"),kCFStringEncodingUTF8);
    [result autorelease];
     return result;
}

- (NSString*)URLDecodedString
{
     NSString *result = (NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault,
               (CFStringRef)self, CFSTR(""),  kCFStringEncodingUTF8);
    [result autorelease];
     return result;
}

@end

参考:
RFC2396 – Uniform Resource Identifiers (URI): Generic Syntax
RFC3986 – Uniform Resource Identifier (URI): Generic Syntax
NSString Class Reference
CFURL Reference 
详解Javascript中的Url编码/解码
A Better URL Encoding Method
Objective-C 对 URL 进行 URLEncode 编码
URL Encoding

本文出自 清风徐来,水波不兴 的博客,转载时请注明出处及相应链接。

本文永久链接: http://www.winddisk.com/2012/05/26/objective_c_url_encode/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值