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

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

问题描述

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



我有足够的长破折号,Word报价等等显示在我的XML输出和导致错误如果我有一个用户的输入作为一个NSString对象,我想要转换它的解析器,因为解析器对这些字符处理不好,导致数据丢失。



<到Base64(我有一个实用程序方法),然后将这些字节写入XML文件,代替NSString。我知道这可能会占用更多的空间,但至少我不会再处理验证问题了。



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

  NSString * loadedData = @8d72 ... ; 

如何从这种形式转换成人类可读的格式?整个编码过程对我有点难以理解,但我认为这是一个真正可靠的方式,以确保奇怪的用户输入正确地保存在我的XML文件。

解决方案

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



然后我写了这些快速方法的上述方法,并允许我将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 * decryptptedStr = [[NSString alloc] initWithData:base64Data encoding:NSUnicodeStringEncoding];

return [decryptedStr autorelease];
}

修改我在前面记录了我的代码,这里是我上面提到的 NSStringUtil 方法。注意我没有创作这个代码,但它已经工作很好多年:

  +(NSData *)base64DataFromString: *)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;
}

输入[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 [result appendBytes:& output [i] length:1];
}
}

if(flbreak){
break;
}
}
}

返回结果;
}

+(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)<< ((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 [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天全站免登陆