逃脱iOS上的é等特殊字符的百分比

时间:2012-11-14 14:48:36

标签: ios nsstring

我目前正在努力避免在iOS上转义特殊字符的百分比,例如包含在查询参数值中的“é”。

我正在使用AFNetworking,但问题并非特定于此。

“é”字符应该被百分比转义为“%E9”,但结果是“%C3%A9”。原因是因为“é”表示为UTF8中的那2个字节。

实际的转义百分比方法是众所周知的,我将UTF8作为字符串编码传递。字符串本身是@“é”。

static NSString * AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(NSString *string, NSStringEncoding encoding) 
{
    static NSString * const kAFCharactersToBeEscaped = @":/?&=;+!@#$()~";
    static NSString * const kAFCharactersToLeaveUnescaped = @"[].";

    return (__bridge_transfer  NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kAFCharactersToLeaveUnescaped, (__bridge CFStringRef)kAFCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding));
}

我曾希望传递UTF16字符串编码可以解决它,但事实并非如此。结果是“%FF%FE%E9%00”在这种情况下,它包含“%E9”但我必须遗漏一些明显的东西。

不知怎的,我无法理解它。 任何指针都会很棒。

1 个答案:

答案 0 :(得分:1)

RFC 3986解释说,除非您编码的字符属于未保留的US-​​ASCII范围,否则约定是将字符转换为(在本例中为UTF8编码的)字节值,并且使用该值作为编码基数百分比。

您所看到的行为是正确的。

UTF-8与UTF-16的编码值之间的差异是由于几个因素造成的。

编码差异

首先,实际定义各个编码的方式不同。 UTF-16将始终使用两个字节来表示其字符,并且基本上将高阶字节与低阶字节连接以定义代码。 (这些字节的排序取决于代码是编码为Little Endian还是Big Endian。)另一方面,UTF-8使用动态字节数,具体取决于字符存在的Unicode代码页中的位置。 UTF-8关于它将使用多少字节的方式是通过在第一个字节本身中设置的位。

因此,如果我们看一下C3 A9,那就转换成以下几位:

1100 0011 1010 1001

RFC 2279,我们看到'1'的终止'0'表示将使用多少字节 - 在这种情况下,2。剥离最初的110元数据,我们从第一个字节开始留下00011:表示实际值的最左边的位。

对于下一个字节(1010 1001),再次从RFC我们看到,对于每个后续字节,10将是实际值的“前缀”元数据。剥离它,我们留下了101001

连接实际值位,我们最终得到00011 101001,基数为10 233,基数为16为E9

编码识别

从UTF-16值(%FF%FE%E9%00)中特别考虑的另一件事来自最初的RFC,它提到在编码值本身中没有使用的编码的明确定义。因此,在这种情况下,iOS是“作弊”,为您提供使用何种编码的指示。 FF FE是UTF-16编码文件中使用的众所周知的字节排序标记,表示UTF-16是使用的编码。至于E9 00,如上所述,UTF-16总是使用两个字节。在这种情况下,由于它的所有数据都可以用1个字节表示,另一个数据只是空。