URL编/解码的Objective-C语言实现
1.1、URL编码

Objective-C中提供了函数stringByAddingPercentEscapesUsingEncoding可以对中文和一些特殊字符进行编码,但是它的功能并不完善,对一些较为特殊的字符无效。建议使用下面我们自己实现的算法,这样与java.net.URLEncoder的结果就是一致的。

Objective-C头文件:

#import <Foundation/Foundation.h>

@interface OCURL : NSObject

+ (NSString*) encode:(NSData*)data;

@end

Objective-C实现文件:

#import "OCURL.h"

@implementation OCURL

+ (NSString*) encode:(NSData*)data {
    NSString *table = @"0123456789ABCDEF";

    NSInteger inputLength = input.length;
    Byte *inputBytes = (Byte*)input.bytes;

    //以最坏的情况分配内存
    Byte outputBytes[3 * inputLength];
    NSInteger outputLength = 0;

    for (int i = 0; i < inputLength; i++) {
        unichar c = inputBytes[i];

        //这些字符保持原样
        if ((c >= '0' && c <= '9')
            || (c >= 'a' && c <= 'z')
            || (c >= 'A' && c <= 'Z')) {
            outputBytes[outputLength++] = c;
        } else if (c == '-' || c == '_' || c == '.' || c == '*') {
            //这些字符保持原样
            outputBytes[outputLength++] = c;
        } else if (c == ' ') { //把空格编码成+
            outputBytes[outputLength++] = '+';
        } else {
            //向右移动4bit,获得高4bit
            NSInteger highByte = inputBytes[i] >> 4;
            //与0x0F做位与运算,获得低4bit
            NSInteger lowByte = inputBytes[i] & 0x0F;
            outputBytes[outputLength++] = '%';
            outputBytes[outputLength++] = [table characterAtIndex: highByte];
            outputBytes[outputLength++] = [table characterAtIndex: lowByte];
        }
    }
    NSData *data = [[NSData alloc] initWithBytes:outputBytes length:outputLength];
    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}

@end
1.2、URL解码

Objective-C头文件:

#import <Foundation/Foundation.h>

@interface OCURL : NSObject

+ (NSData*) decode:(NSString*)input;

@end

Objective-C实现文件:

#import "OCURL.h"

@implementation OCURL

//把16进制字符转换成10进制表示的数字
+ (NSInteger) hex2dec:(unichar)c {
    if ('0' <= c && c <= '9') {
        return c - '0';
    } else if ('a' <= c && c <= 'f') {
        return c - 'a' + 10;
    } else if ('A' <= c && c <= 'F') {
        return c - 'A' + 10;
    } else {
        return 0;
    }
}

+ (NSData*) decode:(NSString*)input {
    if (input) {
        NSInteger inputLength = input.length;
        NSInteger outputLength = 0;
        Byte outputBytes[inputLength];
        for (int i = 0; i < inputLength; i++) {
            unichar c = [input characterAtIndex:i];
            if (c == '%') {
                unichar c1 = [input characterAtIndex:++i];
                unichar c0 = [input characterAtIndex:++i];
                outputBytes[outputLength++] = [OCURL hex2dec:c1] * 16 + [OCURL hex2dec:c0];
            } else if(c == '+') {
                outputBytes[outputLength++] = ' ';
            } else {
                outputBytes[outputLength++] = c;
            }
        }
        return [[NSData alloc] initWithBytes:outputBytes length:outputLength];
    }
    return nil;
}

@end