代码之家  ›  专栏  ›  技术社区  ›  Hoang Pham

Objective-c编码字符串?

  •  70
  • Hoang Pham  · 技术社区  · 14 年前

    我想得到这些特定字母的百分比编码字符串,如何在objective-c中实现这一点?

    Reserved characters after percent-encoding
    !   *   '   (   )   ;   :   @   &   =   +   $   ,   /   ?   #   [   ]
    %21 %2A %27 %28 %29 %3B %3A %40 %26 %3D %2B %24 %2C %2F %3F %23 %5B %5D
    

    Percent-encoding wiki

    myURL = @"someurl/somecontent"
    

    我希望字符串看起来像:

    myEncodedURL = @"someurl%2Fsomecontent"
    

    stringByAddingPercentEscapesUsingEncoding: NSASCIIStringEncoding 但它已经不起作用,结果仍然与原始字符串相同。请给我建议。

    8 回复  |  直到 14 年前
        1
  •  143
  •   Dave DeLong    14 年前

    我发现两者 stringByAddingPercentEscapesUsingEncoding: CFURLCreateStringByAddingPercentEscapes() 这是不够的。这个 NSString

    为了解决这个问题,我创建了一个 NSString字符串 category方法来正确编码字符串。它会把所有的东西 [a-zA-Z0-9.-_~] + (根据 this specification ). 它还将正确处理编码unicode字符。

    - (NSString *) URLEncodedString_ch {
        NSMutableString * output = [NSMutableString string];
        const unsigned char * source = (const unsigned char *)[self UTF8String];
        int sourceLen = strlen((const char *)source);
        for (int i = 0; i < sourceLen; ++i) {
            const unsigned char thisChar = source[i];
            if (thisChar == ' '){
                [output appendString:@"+"];
            } else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' || 
                       (thisChar >= 'a' && thisChar <= 'z') ||
                       (thisChar >= 'A' && thisChar <= 'Z') ||
                       (thisChar >= '0' && thisChar <= '9')) {
                [output appendFormat:@"%c", thisChar];
            } else {
                [output appendFormat:@"%%%02X", thisChar];
            }
        }
        return output;
    }
    
        2
  •  105
  •   Chris Nolet Chen_Wayne    9 年前

    iOS7SDK现在有了一个更好的替代方案 stringByAddingPercentEscapesUsingEncoding 这允许您指定要转义除某些允许的字符外的所有字符。如果您将URL分为以下几个部分进行构建,则效果很好:

    NSString * unescapedQuery = [[NSString alloc] initWithFormat:@"?myparam=%d", numericParamValue];
    NSString * escapedQuery = [unescapedQuery stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    NSString * urlString = [[NSString alloc] initWithFormat:@"http://ExampleOnly.com/path.ext%@", escapedQuery];
    

    [NSCharacterSet URLHostAllowedCharacterSet]
    [NSCharacterSet URLUserAllowedCharacterSet]
    [NSCharacterSet URLPasswordAllowedCharacterSet]
    [NSCharacterSet URLPathAllowedCharacterSet]
    [NSCharacterSet URLFragmentAllowedCharacterSet]
    

    [NSCharacterSet URLQueryAllowedCharacterSet] 包括 全部的 URL的查询部分(以 ? # 对于碎片,如果有的话)包括 ? & = 零件

    NSMutableCharacterSet * URLQueryPartAllowedCharacterSet; // possibly defined in class extension ...
    
    // ... and built in init or on first use
    URLQueryPartAllowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
    [URLQueryPartAllowedCharacterSet removeCharactersInString:@"&+=?"]; // %26, %3D, %3F
    
    // then escape variables in the URL, such as values in the query and any fragment:
    NSString * escapedValue = [anUnescapedValue stringByAddingPercentEncodingWithAllowedCharacters:URLQueryPartAllowedCharacterSet];
    NSString * escapedFrag = [anUnescapedFrag stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
    NSString * urlString = [[NSString alloc] initWithFormat:@"http://ExampleOnly.com/path.ext?myparam=%@#%@", escapedValue, escapedFrag];
    NSURL * url = [[NSURL alloc] initWithString:urlString];
    

    unescapedValue 甚至可以是整个URL,例如回调或重定向:

    NSString * escapedCallbackParamValue = [anAlreadyEscapedCallbackURL stringByAddingPercentEncodingWithAllowedCharacters:URLQueryPartAllowedCharacterSet];
    NSURL * callbackURL = [[NSURL alloc] initWithString:[[NSString alloc] initWithFormat:@"http://ExampleOnly.com/path.ext?callback=%@", escapedCallbackParamValue]];
    

    NSURL initWithScheme:(NSString *)scheme host:(NSString *)host path:(NSString *)path 对于带有查询字符串的URL,因为它将向路径添加更多的转义百分比。

        3
  •  5
  •   Dan Ray    14 年前
    NSString *encodedString = [myString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
    

    注意--新字符串将 autorelease

        4
  •  5
  •   user19164    13 年前

    NSString的 stringByAddingPercentEscapesUsingEncoding: 看起来像你要找的。

    编辑 CFURLCreateStringByAddingPercentEscapes 相反。 originalString 可以是 NSString 或者 CFStringRef

    CFStringRef newString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, originalString, NULL, CFSTR("!*'();:@&=+@,/?#[]"), kCFStringEncodingUTF8);
    

    请注意,这是未经测试。你应该看一看 documentation page ,免费搭桥的想法,等等。

    另外,我也不知道(在我的脑子里)在 legalURLCharactersToBeEscaped

    我把这个答案做成一个社区wiki,这样对CoreFoundation有更多了解的人就可以做出改进。

        5
  •  5
  •   Eneko Alonso    8 年前

    // https://tools.ietf.org/html/rfc3986#section-2.2
    let rfc3986Reserved = NSCharacterSet(charactersInString: "!*'();:@&=+$,/?#[]")
    let encoded = "email+with+plus@example.com".stringByAddingPercentEncodingWithAllowedCharacters(rfc3986Reserved.invertedSet)
    

    输出: email%2Bwith%2Bplus%40example.com

        6
  •  2
  •   bhavinb    13 年前

    ASI HttpRequest library 在objective-c程序中(我不能高度推荐),您可以在其ASIFormDataRequest对象上使用“encodeURL”助手API。不幸的是,API不是静态的,所以在您的项目中使用它的实现创建一个扩展可能是值得的。

    - (NSString*)encodeURL:(NSString *)string
    {
        NSString *newString = NSMakeCollectable([(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, CFSTR(":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`"), CFStringConvertNSStringEncodingToEncoding([self stringEncoding])) autorelease]);
        if (newString) {
            return newString;
        }
        return @"";
    }
    

    如您所见,它本质上是一个包装器 CFURLCreateStringByAddingPercentEscapes

        7
  •  0
  •   Ben Baron    8 年前

    在我注意到Rob的答案之前,我把Dave的答案传给了Swift,这个答案似乎很有效,而且因为它更干净而更受欢迎。如果有人感兴趣,我就把它留在这里:

    public extension String {
    
        // For performance, I've replaced the char constants with integers, as char constants don't work in Swift.
    
        var URLEncodedValue: String {
            let output = NSMutableString()
            guard let source = self.cStringUsingEncoding(NSUTF8StringEncoding) else {
                return self
            }
            let sourceLen = source.count
    
            var i = 0
            while i < sourceLen - 1 {
                let thisChar = source[i]
                if thisChar == 32 {
                    output.appendString("+")
                } else if thisChar == 46 || thisChar == 45 || thisChar == 95 || thisChar == 126 ||
                    (thisChar >= 97 && thisChar <= 122) ||
                    (thisChar >= 65 && thisChar <= 90) ||
                    (thisChar >= 48 && thisChar <= 57) {
                        output.appendFormat("%c", thisChar)
                } else {
                    output.appendFormat("%%%02X", thisChar)
                }
    
                i++
            }
    
            return output as String
        }
    }
    
        8
  •  0
  •   lebelinoz    7 年前

     var str = "someurl/somecontent"
    
     let percentEncodedString = str.addingPercentEncoding(withAllowedCharacters: .alphanumerics)