Thursday, April 28, 2011

How to convert NSData to byte array in iPhone?

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?

From stackoverflow
  • 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.

    iPhoney : After I add [data getBytes:byteData length:len]; the byteData turns out to be invalid. What might be the problem?
    Nicholas Riley : Try printing the NSData and seeing if it matches; then check the length and make sure it looks like what you're expecting. If the data is a string, you can also try -[NSString stringWithContentsOfFile].
    iPhoney : I find out the problem: the length shouldn't be a variable. It should be Byte byteData[255];
    Nicholas Riley : Too much Java for me recently. :-) Glad you got it figured out.
  • 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.

    iPhoney : The byteData is invalid. What might be the problem?
  • 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:len: 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.

    iPhoney : Byte byteData = malloc(len); pops up a warning saying "initialization makes interger from pointer without a cast". And byteData turns out to be a byte variable, not a byte array. Any ideas about this?
    Jason Coco : There was a small typo in the code, it should work now as matt intended.
    iPhoney : Yes. The second parameter of memcpy should be [data bytes].
    Matt Gallagher : Thanks, iphony, I've fixed the memcpy 2nd parameter.
    Matt Gallagher : Also, in case you didn't spot it yourself... Byte byteData = malloc(len); doesn't work because byteData must be declared as a pointer, i.e. Byte *byteData.

0 comments:

Post a Comment