将NSString转换为Base64数据以进行XML序列化

5

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

我已经厌倦了长破折号、Word引号等在我的XML输出中出现并导致解析错误的问题,这通常会由于解析器对这些字符的处理不当而导致数据丢失。

如果我有一个用户输入的NSString对象,我想将其转换为Base64(我有一个实用程序方法),然后将这些字节写入XML文件,代替NSString。我知道这可能会占用更多的空间,但至少我不必再处理验证问题了。

我的问题是,如何将NSData字节(在NSLog语句中看起来像<8d72...>)转换为NSString,而不使用编码以获取原始值。我希望那些实际的字节,就像它们在日志语句中出现的那样,被转换为NSString。最后(在加载这个序列化的数据时),如果你有一个NSString:

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

如何将此表单转换为可读格式?整个编码过程对我来说有点困难,但我认为这是确保在我的XML文件中正确保存奇怪用户输入的一种坚实方式。

1个回答

11

明白了。我正在使用这篇答案中的编解码方法将我的NSString对象转换为NSData对象,反之亦然: Any base64 library on iphone-sdk?

然后我编写了这些快速方法来利用上述方法,并允许我将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* 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;
}

NSStringUtil 是我编写的一个类,它简单地包含了在我的回答中描述的 base64DataFromString:base64StringFromData: 方法。 - Craig Otis
请问能否给我展示一下NSStringUtil类……我想要把我的Base64转换成NSString……但是我遇到了NSStringUtil的错误。 - Baby Groot
请使用我回答中的链接中提供的方法:https://dev59.com/E3RC5IYBdhLWcg3wKtv2#800976 - Craig Otis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接