解析NSData对象以获取信息

时间:2012-02-29 21:38:23

标签: iphone ios nsdata

我有一个NSData对象从我的服务器返回,它的内容各不相同,但坚持特定的结构。

我想知道(跳过一些示例代码)如何使用此对象来获取我需要的数据。

对象内部数据对象的结构就像这样

  • 领先值( UInt16 ) - (告诉我它的响应部分)
  • 字符串的大小( UInt32 号码 - ( UInt32
  • 字符串(非空终止),即后跟前一个值。

我一直在阅读Binary Data Programming Guide,但这只是真正告诉我如何将我的数据放入新的NSData对象以及访问和计算字节数。

我坚持的是我怎么说动态抓取信息。检查NSdata对象的第一个前导值,如果它的字符串或int,则获取字符串或int并移动到下一个前导值..

任何建议或示例代码都会非常有用..只是因为我从未在目标C中尝试过这样的事情而陷入心灵障碍。

2 个答案:

答案 0 :(得分:1)

定义自己的内部结构并将指针强制转换为它:

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

编辑: 如果你需要循环阅读它们:

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

答案 1 :(得分:1)

其中一些取决于您的服务器的编写方式,以便将数据编码为发送给您的数据。假设它使用标准网络字节顺序(big-endian)对数值进行编码,你会希望它转换为iOS的正确字节顺序(我相信它总是小端)。

我会接近这样的事情:

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);
        free(cstring);
        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
    }
}