将NSData字节数组转换为字符串?

时间:2015-08-08 16:05:03

标签: objective-c json cocoa nsdata

我有一个NSData对象。我需要将其字节转换为字符串并作为JSON发送。 description返回十六进制并且不可靠(根据各种SO海报)。所以我正在查看这样的代码:

NSUInteger len = [imageData length];
Byte *byteData = (Byte*)malloc(len);
[imageData getBytes:&byteData length:len];

然后如何将byteData作为JSON发送?我想发送原始字节。

CODE:

NSString *jsonBase64 = [imageData base64EncodedString];
NSLog(@"BASE 64 FINGERPRINT: %@", jsonBase64);
NSData *b64 = [NSData dataFromBase64String:jsonBase64];
NSLog(@"Equal: %d", [imageData isEqualToData:b64]);
NSLog(@"b64: %@", b64);
NSLog(@"original: %@", imageData);
NSString *decoded = [[NSString alloc] initWithData:b64 encoding:NSUTF8StringEncoding];
NSLog(@"decoded: %@", decoded);

除了最后一行 - decoded之外,我获得了所有值的值。 哪会告诉我原始字节没有格式化为NSUTF8encoding?

3 个答案:

答案 0 :(得分:6)

您是否尝试过使用此类内容:

@implementation NSData (Base64)
- (NSString *)base64EncodedString
{
    return [self base64EncodedStringWithWrapWidth:0];
}

这会将你的NSData转换为base64字符串,而另一方面你需要解码它。

编辑:@Lucas说你可以这样做:

NSString *myString = [[NSString alloc] initWithData:myData encoding:NSUTF8StringEncoding];

但由于一些特殊的字符,我对这个方法有一些问题,因此我开始使用base64字符串进行通信。

EDIT3:尝试此方法base64EncodedString

    @implementation NSData (Base64)

    - (NSString *)base64EncodedString
    {
        return [self base64EncodedStringWithWrapWidth:0];
    }

    //Helper Method
    - (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth
    {
        //ensure wrapWidth is a multiple of 4
        wrapWidth = (wrapWidth / 4) * 4;

        const char lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

        long long inputLength = [self length];
        const unsigned char *inputBytes = [self bytes];

        long long maxOutputLength = (inputLength / 3 + 1) * 4;
        maxOutputLength += wrapWidth? (maxOutputLength / wrapWidth) * 2: 0;
        unsigned char *outputBytes = (unsigned char *)malloc((NSUInteger)maxOutputLength);

        long long i;
        long long outputLength = 0;
        for (i = 0; i < inputLength - 2; i += 3)
        {
            outputBytes[outputLength++] = lookup[(inputBytes[i] & 0xFC) >> 2];
            outputBytes[outputLength++] = lookup[((inputBytes[i] & 0x03) << 4) | ((inputBytes[i + 1] & 0xF0) >> 4)];
            outputBytes[outputLength++] = lookup[((inputBytes[i + 1] & 0x0F) << 2) | ((inputBytes[i + 2] & 0xC0) >> 6)];
            outputBytes[outputLength++] = lookup[inputBytes[i + 2] & 0x3F];

            //add line break
            if (wrapWidth && (outputLength + 2) % (wrapWidth + 2) == 0)
            {
                outputBytes[outputLength++] = '\r';
                outputBytes[outputLength++] = '\n';
            }
        }

        //handle left-over data
        if (i == inputLength - 2)
        {
            // = terminator
            outputBytes[outputLength++] = lookup[(inputBytes[i] & 0xFC) >> 2];
            outputBytes[outputLength++] = lookup[((inputBytes[i] & 0x03) << 4) | ((inputBytes[i + 1] & 0xF0) >> 4)];
            outputBytes[outputLength++] = lookup[(inputBytes[i + 1] & 0x0F) << 2];
            outputBytes[outputLength++] =   '=';
        }
        else if (i == inputLength - 1)
        {
            // == terminator
            outputBytes[outputLength++] = lookup[(inputBytes[i] & 0xFC) >> 2];
            outputBytes[outputLength++] = lookup[(inputBytes[i] & 0x03) << 4];
            outputBytes[outputLength++] = '=';
            outputBytes[outputLength++] = '=';
        }

        if (outputLength >= 4)
        {
            //truncate data to match actual output length
            outputBytes = realloc(outputBytes, (NSUInteger)outputLength);
            return [[NSString alloc] initWithBytesNoCopy:outputBytes
                                                  length:(NSUInteger)outputLength
                                                encoding:NSASCIIStringEncoding
                                            freeWhenDone:YES];
        }
        else if (outputBytes)
        {
            free(outputBytes);
        }
        return nil;
    }

答案 1 :(得分:6)

  1. 在之前的Stack帖子中将字符串视为“不可靠”的原因是因为他们也试图使用NSData对象,其中结尾字节未正确终止 NULL

    NSString *jsonString = [NSString stringWithUTF8String:[nsDataObj bytes]];
    // This is unreliable because it may result in NULL string values
    
  2. 以下示例应该为您提供所需的结果,因为NSData字节字符串将正确终止:

    NSString *jsonString = [[NSString alloc]  initWithBytes:[nsDataObj bytes] length:[nsDataObj length] encoding: NSUTF8StringEncoding];
    
  3. 您走在正确的轨道上,希望这能够帮助您解决当前的问题。祝你好运!

    ~EDIT~

    确保从图像中声明您的NSData对象:

    NSData *imageData = [[NSData alloc] init];
    imageData = UIImagePNGRepresentation(yourImage);
    

答案 2 :(得分:3)

NSData转换为NSString时,空终止不是唯一的问题。

NSString不能保存任意二进制数据。它期望编码。

如果您的NSData包含无效的UTF-8序列,initializing the NSString will fail

关于这一点,文档并不完全清楚,但对于initWithData,它说:

  

如果由于某种原因初始化失败,则返回nil(例如   如果数据不代表编码的有效数据。)

另外:JSON规范将字符串定义为sequence of Unicode characters

这意味着即使您能够将原始数据转换为JSON字符串,如果代码执行UTF-8验证,解析也可能在接收端失败。

如果您不想使用Base64take a look at the answers here