How to convert NSData to byte array in iPhone?

IphoneObjective CBytearrayType Conversion

Iphone Problem Overview


I want to convert NSData to a byte array, so I write the following code:

NSData *data = [NSData dataWithContentsOfFile:filePath];
int len = [data length];
Byte byteData[len];
byteData = [data bytes];

But the last line of code pops up an error saying "incompatible types in assignment". What is the correct way to convert the data to byte array then?

Iphone Solutions


Solution 1 - Iphone

You can't declare an array using a variable so Byte byteData[len]; won't work. If you want to copy the data from a pointer, you also need to memcpy (which will go through the data pointed to by the pointer and copy each byte up to a specified length).

Try:

NSData *data = [NSData dataWithContentsOfFile:filePath];
NSUInteger len = [data length];
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, [data bytes], len);

This code will dynamically allocate the array to the correct size (you must free(byteData) when you're done) and copy the bytes into it.

You could also use getBytes:length: as indicated by others if you want to use a fixed length array. This avoids malloc/free but is less extensible and more prone to buffer overflow issues so I rarely ever use it.

Solution 2 - Iphone

You could also just use the bytes where they are, casting them to the type you need.

unsigned char *bytePtr = (unsigned char *)[data bytes];

Solution 3 - Iphone

Already answered, but to generalize to help other readers:

    //Here:   NSData * fileData;
    uint8_t * bytePtr = (uint8_t  * )[fileData bytes];

    // Here, For getting individual bytes from fileData, uint8_t is used.
    // You may choose any other data type per your need, eg. uint16, int32, char, uchar, ... .
    // Make sure, fileData has atleast number of bytes that a single byte chunk would need. eg. for int32, fileData length must be > 4 bytes. Makes sense ?

    // Now, if you want to access whole data (fileData) as an array of uint8_t
    NSInteger totalData = [fileData length] / sizeof(uint8_t);

    for (int i = 0 ; i < totalData; i ++)
    {
        NSLog(@"data byte chunk : %x", bytePtr[i]);
    }

Solution 4 - Iphone

The signature of -[NSData bytes] is - (const void *)bytes. You can't assign a pointer to an array on the stack. If you want to copy the buffer managed by the NSData object into the array, use -[NSData getBytes:]. If you want to do it without copying, then don't allocate an array; just declare a pointer variable and let NSData manage the memory for you.

Solution 5 - Iphone

That's because the return type for [data bytes] is a void* c-style array, not a Uint8 (which is what Byte is a typedef for).

The error is because you are trying to set an allocated array when the return is a pointer type, what you are looking for is the getBytes:length: call which would look like:

[data getBytes:&byteData length:len];

Which fills the array you have allocated with data from the NSData object.

Solution 6 - Iphone

Here's what I believe is the Swift equivalent:

if let data = NSData(contentsOfFile: filePath) {
   let length = data.length
   let byteData = malloc(length)
   memcmp(byteData, data.bytes, length)
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChilly ZhongView Question on Stackoverflow
Solution 1 - IphoneMatt GallagherView Answer on Stackoverflow
Solution 2 - IphonestevexView Answer on Stackoverflow
Solution 3 - IphoneKhulja Sim SimView Answer on Stackoverflow
Solution 4 - IphoneNicholas RileyView Answer on Stackoverflow
Solution 5 - IphoneKendall Helmstetter GelnerView Answer on Stackoverflow
Solution 6 - Iphonejervine10View Answer on Stackoverflow