解析NSData对象以获取信息
我有一个NSData
对象从我的服务器返回,它的内容不同但坚持特定的结构。
我想知道(跳过一些示例代码)如何通过这个对象来获取我需要的数据。
对象内部的数据对象的结构是这样的
- 领先值( UInt16 ) – (告诉我它的响应部分)
- 字符串大小( UInt32 ) 或数字 – ( UInt32 )
- 字符串(非空终止),即后跟下一个前导值。
我一直在阅读二进制数据编程指南,但这只是真正告诉我如何将我的数据放入新的NSData
对象以及访问和计算字节。
我坚持的是我怎么说动态抓取信息。 检查NSdata
对象的第一个前导值,如果它的字符串或int,则获取字符串或int并移动到下一个前导值..
任何建议或示例代码都会非常有用…只是因为我从未在目标C中尝试过这样的事情而陷入心灵障碍。
其中一些取决于服务器的编写方式,将数据编码为发送给您的数据。 假设它使用标准网络字节排序(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 } }
定义自己的内部结构并将指针强制转换为它:
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; }