Преобразование NSString в данные Base64 для сериализации XML - PullRequest
5 голосов
/ 29 января 2011

Я использую класс Apple NSXMLParser для загрузки данных. У меня есть отдельная структура для сериализации моих данных.

С меня хватит длинных черточек, кавычек Word и т. Д., Которые отображаются в моем выводе XML и вызывают ошибки при синтаксическом анализе, которые часто приводят к потере данных из-за плохой обработки этих символов синтаксическим анализатором.

Если у меня есть ввод пользователя в качестве объекта NSString, я хочу преобразовать его в Base64 (для которого у меня есть служебный метод), а затем записать эти байты в файл XML вместо NSString. Я понимаю, что это может занять больше места, но, по крайней мере, мне больше не придется заниматься вопросами проверки.

У меня вопрос: как можно преобразовать байты NSData (которые выглядят как <8d72...> в операторе NSLog) в строку NSString, без , используя кодирование для возврата исходного значения. Я хочу, чтобы эти фактические байты, как они появляются в операторе журнала, были преобразованы в строку NSString. И наконец (при загрузке этих сериализованных данных), если у вас есть строка NSString:

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

Как перейти от этой формы к читабельному формату? Весь процесс кодирования для меня немного сложен для понимания, но я думаю, что это действительно надежный способ убедиться, что странный пользовательский ввод правильно сохраняется в моих XML-файлах.

1 Ответ

11 голосов
/ 30 января 2011

Понял.Я использую методы кодирования / декодирования из этого ответа для преобразования моих объектов NSString в объекты NSData, и наоборот: Любая библиотека base64 на 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...