Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert NSData byte array to string?

I have an NSData object. I need to convert its bytes to a string and send as JSON. description returns hex and is unreliable (according to various SO posters). So I'm looking at code like this:

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

How do I then send byteData as JSON? I want to send the raw bytes.

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);

I get values for everything except for the last line - decoded. Which would indicate to me that the raw bytes are not formatted in NSUTF8encoding?

like image 298
quantumpotato Avatar asked Aug 08 '15 16:08

quantumpotato


2 Answers

  1. The reason the String is being considered 'unreliable' in previous Stack posts is because they too were attempting to use NSData objects where the ending bytes aren't properly terminated with NULL :

    NSString *jsonString = [NSString stringWithUTF8String:[nsDataObj bytes]];
    // This is unreliable because it may result in NULL string values
    
  2. Whereas the example below should give you your desired results because the NSData byte string will terminate correctly:

    NSString *jsonString = [[NSString alloc]  initWithBytes:[nsDataObj bytes] length:[nsDataObj length] encoding: NSUTF8StringEncoding];
    

You were on the right track and hopefully this is able to help you solve your current problem. Best of luck!

~ EDIT ~

Make sure you are declaring your NSData Object from an image like so:

NSData *imageData = [[NSData alloc] init];
imageData = UIImagePNGRepresentation(yourImage);
like image 158
ChrisHaze Avatar answered Oct 14 '22 19:10

ChrisHaze


Have you tried using something like this:

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

This will turn your NSData in a base64 string, and on the other side you just need to decode it.

EDIT: @Lucas said you can do something like this:

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

but i had some problem with this method because of some special characters, and because of that i started using base64 strings for communication.

EDIT3: Trys this method 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;
    }
like image 23
rob180 Avatar answered Oct 14 '22 19:10

rob180