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
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