парсинг NSData объект для информации - PullRequest
0 голосов
/ 01 марта 2012

У меня есть объект NSData, возвращающийся с моего сервера, он различается по своему содержанию, но придерживается определенной структуры.

Я хотел бы знать (надеюсь, с некоторым примером кода), как работать с этим объектом, чтобы получить из него нужные мне данные.

структура объектов данных внутри объектовкак это

  • начальное значение ( UInt16 ) - (говорит, что это за раздел ответа)
  • Размер строки ( UInt32 ) или число - ( UInt32 )
  • Строка (не завершена нулем), т.е. за ней следует следующее начальное значение.

IЯ читал Руководство по программированию двоичных данных , но это только показывает, как поместить мои данные в новые NSData объекты и получить доступ и сравнить байты.

То, что я застрялна это, как я могу сказать, получить информацию динамически.Проверьте, что NSdata объектов сначала первое значение, выяснить, если его строка или int затем получить строку или int и перейти к следующему ведущему значению ..

любые предложения или пример кода будет действительно полезным .. просто застрялв состоянии блока ума, поскольку я никогда не пытался сделать что-либо подобное в цели С.

Ответы [ 2 ]

1 голос
/ 01 марта 2012

Отчасти это зависит от того, как ваш сервер написан для кодирования данных в то, что он отправляет вам. Предполагая, что он кодирует числовые значения с использованием стандартного сетевого порядка байтов (big-endian), вы захотите, чтобы он был преобразован в правильный порядок байтов для iOS (я полагаю, что это всегда little-endian).

Я бы подошел к этому примерно так:

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
    }
}
1 голос
/ 01 марта 2012

Определите свои собственные внутренние структуры и наведите указатель на него:

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

EDIT: Если вам нужно прочитать их в цикле:

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;
}
...