我有一个NSData
对象从我的服务器返回,它的内容各不相同,但坚持特定的结构。
我想知道(跳过一些示例代码)如何使用此对象来获取我需要的数据。
对象内部数据对象的结构就像这样
我一直在阅读Binary Data Programming Guide,但这只是真正告诉我如何将我的数据放入新的NSData
对象以及访问和计算字节数。
我坚持的是我怎么说动态抓取信息。检查NSdata
对象的第一个前导值,如果它的字符串或int,则获取字符串或int并移动到下一个前导值..
任何建议或示例代码都会非常有用..只是因为我从未在目标C中尝试过这样的事情而陷入心灵障碍。
答案 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
}
}