我使用Apple的NSXMLParser类来加载数据。我有一个单独的框架来序列化我的数据。
我已经有足够的长短划线,Word引号等显示在我的XML输出中并在解析时导致错误,这通常会导致数据丢失,因为解析器对这些字符的处理不当。
如果我将用户的输入作为NSString对象,我想将其转换为Base64(我有一个实用工具方法),然后将这些字节写入XML文件,代替NSString。我知道这可能会占用更多空间,但至少我不必再处理验证问题了。
我的问题是,如何将NSData字节(在NSLog语句中看起来像<8d72...>
)转换为NSString,没有使用编码来获取原始值。我希望将那些出现在日志语句中的实际字节转换为NSString。最后(加载此序列化数据时),如果您有NSString:
NSString *loadedData = @"8d72...";
如何从这种形式转变为人类可读的格式?整个编码过程对我来说有点难以理解,但我认为这是确保在我的XML文件中正确保留奇怪的用户输入的一种非常可靠的方法。
答案 0 :(得分:11)
知道了。我正在使用此答案中的编码/解码方法将我的NSString对象转换为NSData对象,反之亦然: Any base64 library on iphone-sdk?
然后我编写了这些使用上述方法的快速方法,并允许我将Base64字符串数据写入XML。加载效果很好,已经过中文字符,单词字符等测试。如果需要,也可以解析这些,但至少错误不在解析器中。 (如果您没有正确处理错误,很容易导致数据丢失。)
+ (NSString *)toBase64String:(NSString *)string {
NSData *data = [string dataUsingEncoding: NSUnicodeStringEncoding];
NSString *ret = [NSStringUtil base64StringFromData:data length:[data length]];
return ret;
}
+ (NSString *)fromBase64String:(NSString *)string {
NSData *base64Data = [NSStringUtil base64DataFromString:string];
NSString* decryptedStr = [[NSString alloc] initWithData:base64Data encoding:NSUnicodeStringEncoding];
return [decryptedStr autorelease];
}
修改:由于原始链接已关闭,我从前一段时间开始搜索我的代码,这是我上面提到的NSStringUtil
方法。注意我没有编写此代码,但多年来一直运行良好:
+ (NSData *)base64DataFromString: (NSString *)string {
unsigned long ixtext, lentext;
unsigned char ch, input[4], output[3];
short i, ixinput;
Boolean flignore, flendtext = false;
const char *temporary;
NSMutableData *result;
if (!string) {
return [NSData data];
}
ixtext = 0;
temporary = [string UTF8String];
lentext = [string length];
result = [NSMutableData dataWithCapacity: lentext];
ixinput = 0;
while (true) {
if (ixtext >= lentext) {
break;
}
ch = temporary[ixtext++];
flignore = false;
if ((ch >= 'A') && (ch <= 'Z')) {
ch = ch - 'A';
} else if ((ch >= 'a') && (ch <= 'z')) {
ch = ch - 'a' + 26;
} else if ((ch >= '0') && (ch <= '9')) {
ch = ch - '0' + 52;
} else if (ch == '+') {
ch = 62;
} else if (ch == '=') {
flendtext = true;
} else if (ch == '/') {
ch = 63;
} else {
flignore = true;
}
if (!flignore) {
short ctcharsinput = 3;
Boolean flbreak = false;
if (flendtext) {
if (ixinput == 0) {
break;
}
if ((ixinput == 1) || (ixinput == 2)) {
ctcharsinput = 1;
} else {
ctcharsinput = 2;
}
ixinput = 3;
flbreak = true;
}
input[ixinput++] = ch;
if (ixinput == 4) {
ixinput = 0;
unsigned char0 = input[0];
unsigned char1 = input[1];
unsigned char2 = input[2];
unsigned char3 = input[3];
output[0] = (char0 << 2) | ((char1 & 0x30) >> 4);
output[1] = ((char1 & 0x0F) << 4) | ((char2 & 0x3C) >> 2);
output[2] = ((char2 & 0x03) << 6) | (char3 & 0x3F);
for (i = 0; i < ctcharsinput; i++) {
[result appendBytes: &output[i] length: 1];
}
}
if (flbreak) {
break;
}
}
}
return result;
}
+ (NSString *)base64StringFromData: (NSData *)data length: (NSUInteger)length {
unsigned long ixtext, lentext;
long ctremaining;
unsigned char input[3], output[4];
short i, charsonline = 0, ctcopy;
const unsigned char *raw;
NSMutableString *result;
lentext = [data length];
if (lentext < 1) {
return @"";
}
result = [NSMutableString stringWithCapacity: lentext];
raw = [data bytes];
ixtext = 0;
while (true) {
ctremaining = lentext - ixtext;
if (ctremaining <= 0) {
break;
}
for (i = 0; i < 3; i++) {
unsigned long ix = ixtext + i;
if (ix < lentext) {
input[i] = raw[ix];
} else {
input[i] = 0;
}
}
output[0] = (input[0] & 0xFC) >> 2;
output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4);
output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6);
output[3] = input[2] & 0x3F;
ctcopy = 4;
switch (ctremaining) {
case 1:
ctcopy = 2;
break;
case 2:
ctcopy = 3;
break;
}
for (i = 0; i < ctcopy; i++) {
[result appendString: [NSString stringWithFormat: @"%c", base64EncodingTable[output[i]]]];
}
for (i = ctcopy; i < 4; i++) {
[result appendString: @"="];
}
ixtext += 3;
charsonline += 4;
if ((ixtext % 90) == 0) {
[result appendString: @"\n"];
}
if (length > 0) {
if (charsonline >= length) {
charsonline = 0;
[result appendString: @"\n"];
}
}
}
return result;
}