将NSString转换为Base64数据进行XML序列化 [英] Converting NSString to Base64 Data for XML Serialization

查看:131
本文介绍了将NSString转换为Base64数据进行XML序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用苹果的NSXMLParser类加载数据。我有一个单独的框架来序列化我的数据。



我已经有足够的长的破折号,Word引号等显示在我的XML输出并导致错误当解析时,由于解析器对这些字符的处理不善,这往往导致数据丢失。



如果我有一个用户的输入作为NSString对象,我想转换它到Base64(我有一个实用方法),然后将这些字节写入XML文件,而不是NSString。我明白这可能会占用更多的空间,但至少我不必再处理验证问题。



我的问题是,怎么去将NSData字节(在NSLog语句中看起来像< 8d72 ...> )转换为NSString,不使用使用编码获取原价值回来。我想要这些实际的字节,因为它们出现在日志语句中,被转换为NSString。最后(当加载这个序列化的数据),如果你有一个NSString:

  NSString * loadedData = @8d72 ... ; 

从表单到人类可读的格式如何?整个编码过程对我来说有点困难,但我认为这是一个非常稳固的方法,以确保奇怪的用户输入被正确地保留在我的XML文件中。

解决方案

知道了我使用这个答案的编码/解码方法将NSString对象转换为NSData对象,反之亦然:
iphone-sdk上的任何base64库?



然后我写了这些使用的快速方法的上述方法,并允许我将Base64字符串数据写入XML。加载它很棒,已经用汉字,Word字符等进行了测试。你也可以解析这些,如果你想要的,但至少错误不在解析器中。 (如果您没有正确处理错误,可能会导致数据丢失)。

  +(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 * decryptptedStr = [[NSString alloc] initWithData:base64Data encoding:NSUnicodeStringEncoding];

return [decryptptedStr 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];

输出[0] =(char0 <2)| ((char1& 0x30)>> 4);
output [1] =((char1& 0x0F)<< 4)| ((char2& 0x3C)>> 2);
output [2] =((char2& 0x03)<< 6)| (char3& 0x3F); (i = 0; i [result appendBytes:& output [i] length:1];


}
}

if(flbreak){
break;
}
}
}

返回结果;
}

+(NSString *)base64StringFromData:(NSData *)数据长度:(NSUInteger)length {
unsigned long ixtext,lentext;
long ctremaining;
无符号字符输入[3],输出[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;
}
}

输出[0] =(输入[0]& 0xFC)>> 2;
output [1] =((input [0]& 0x03)<< 4)| ((输入[1]& 0xF0)>> 4);
output [2] =((input [1]& 0x0F)<< 2)| ((输入[2]& 0xC0)>> 6);
output [3] = input [2]& 0x3F的;

ctcopy = 4;

开关(ctremaining){
案例1:
ctcopy = 2;
break;
案例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:@\\\
];
}

if(length> 0){
if(charsonline> = length){
charsonline = 0;

[result appendString:@\\\
];
}
}
}

返回结果;
}


I use Apple's NSXMLParser class to load data. I have a separate framework for serializing my data.

I've had enough of the long dash, the Word quotes, etc. showing up in my XML output and causing errors when parsing, which often result in data loss due to the parser's poor handling of those characters.

If I have a user's input as an NSString object, I want to convert it to Base64 (which I have a utility method for), then write those bytes to the XML file, in place of the NSString. I understand this might take up more space, but at least I won't have to deal with the validation issues any more.

My question is, how does one go about converting the NSData bytes (which look like <8d72...> in an NSLog statement) to an NSString, without using encoding to get the original value back. I want those actual bytes, as they appear in the log statement, to be converted to an NSString. And finally (when loading this serialized data), if you have an NSString:

NSString *loadedData = @"8d72...";

How does one go from this form to the human-readable format? The whole encoding process is a little difficult for me to understand, but I think this is a really solid way to ensure that weird user input is properly persisted in my XML files.

解决方案

Got it. I'm using the encoding/decoding methods from this answer to convert my NSString objects to NSData objects, and vice versa: Any base64 library on iphone-sdk?

And then I wrote these quick methods that make use of the above methods, and allow me to write the Base64 string data to XML. Loading it up works great, has been tested with Chinese characters, Word characters, etc. You can also parse these out if you want, but at least the error isn't in the parser. (Which could easily result in data loss if you don't handle the errors properly.)

+ (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];
}

Edit: As the original link is down, I hunted down my code from a while ago, here are my NSStringUtil methods mentioned above. Note I did not author this code, but it has been working well for years:

+ (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;
}

这篇关于将NSString转换为Base64数据进行XML序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆