parsing NSData object for information

I have a NSData object coming back from my server, it varies in its content but sticks to a particular structure.

I would like to know (hopfully with some example code) how to work though this object to get the data I need out of it.

  • Append NSData to a file in Objective C
  • Finding file type of NSData recieved from server
  • Convert nsdictionary to nsdata
  • Converting UIImage to NSData and NSData to NSString for posting images to a server
  • Converting hex string to hex data
  • Camera image orientation
  • the structure of the data objects inside the objects are like this

    • leading value (UInt16) – (tells me what section of the response it is)
    • Size of string (UInt32) or number – (UInt32)
    • String (not null terminated) i.e. followed by the next leading value.

    I have been reading through the Binary Data Programming Guide however that’s only really showing me how to put my data into new NSData objects and accessing and compairing the bytes.

    The thing I am stuck on is how do I say grab the info dynamically. Check the NSdata objects first leading value figure out if its string or int then get the string or int and move onto the next leading value..

    any suggestions or example code would be really helpfull.. just stuck in abit of a mind block as I have never attempted anything like this in objective C.

    2 Solutions Collect From Internet About “parsing NSData object for information”

    Some of this depends on how your server is written to encode the data into what it is sending you. Assuming it is encoding the numeric values using standard network byte ordering (big-endian) you will want it converted to the correct byte-ordering for iOS (I believe that is always little-endian).

    I would approach it something like this:

    uint16_t typeWithNetworkOrdering, typeWithLocalOrdering;
    uint32_t sizeWithNetworkOrdering, sizeWithLocalOrdering;
    char *cstring = NULL;
    uint32_t numberWithNetworkOrdering, numberWithLocalOrdering;
    const void *bytes = [myData bytes];
    NSUInteger length = [myData length];
    while (length > 0) {
        memcpy(&typeWithNetworkOrdering, bytes, sizeof(uint16_t));
        bytes += sizeof(uint16_t);
        length -= sizeof(uint16_t);
        memcpy(&sizeWithNetworkOrdering, bytes, sizeof(uint32_t));
        bytes += sizeof(uint32_t);
        length -= sizeof(uint32_t);
        typeWithLocalOrdering = CFSwapInt16BigToHost(typeWithNetworkOrdering);
        sizeWithLocalOrdering = CFSwapInt32BigToHost(sizeWithNetworkOrdering);
        if (typeWithLocalOrdering == STRING_TYPE) { // STRING_TYPE is whatever type value corresponds to a string
            cstring = (char *) malloc(sizeWithLocalOrdering + 1);
            strncpy(cstring, bytes, sizeWithLocalOrdering);
            cstring[sizeWithLocalOrdering] = '\0';
            NSString *resultString = [NSString stringWithCString:cstring encoding:NSUTF8StringEncoding];
            NSLog(@"String = %@", resultString);
            bytes += sizeWithLocalOrdering;
            length -= sizeWithLocalOrdering;
            // Do whatever you need to with the string
        else if (typeWithLocalOrdering == NUMBER_TYPE) { // NUMBER_TYPE is whatever type value corresponds to a number
            memcpy(&numberWithNetworkOrdering, bytes, sizeof(uint32_t));
            numberWithLocalOrdering = CFSwapInt32BigToHost(numberWithNetworkOrdering);
            NSLog(@"Number = %u", numberWithLocalOrdering);
            bytes += sizeof(uint32_t);
            length -= sizeof(uint32_t);
            // Do whatever you need to with the number

    Define your own internal structs and cast the pointer to it:

    NSData* data;
    struct headerType
        uint16_t type;
        uint32_t length;
    const struct headerType* header=(const struct headerType*)[data bytes]; // get the header of the response
    if (header->type==1)
        const char* text=((const char*)header)+6; // skip the header (16bits+32bits=6 bytes offset)

    If you need to read them in a loop:

    NSData* data;
    const uint8_t* cursor=(const uint8_t*)[data bytes];
    while (true)
        uint16_t type=*((uint16_t*)cursor);
        if (cursor==1)
            // string
            uint32_t length=*((uint32_t*)cursor);
            const char* str=(const char*)cursor;
        else if (cursor==2)
            // another type