Как преобразовать NSData в байтовый массив в iPhone? - PullRequest
45 голосов
/ 07 апреля 2009

Я хочу преобразовать NSData в байтовый массив, поэтому я пишу следующий код:

NSData *data = [NSData dataWithContentsOfFile:filePath];
int len = [data length];
Byte byteData[len];
byteData = [data bytes];

Но в последней строке кода появляется сообщение об ошибке «несовместимые типы в присваивании». Каков правильный способ преобразования данных в байтовый массив?

Ответы [ 6 ]

59 голосов
/ 07 апреля 2009

Вы не можете объявить массив, используя переменную, поэтому Byte byteData[len]; не будет работать. Если вы хотите скопировать данные из указателя, вам также необходимо использовать memcpy (который будет проходить через данные, на которые указывает указатель, и копировать каждый байт до указанной длины).

Попробуйте:

NSData *data = [NSData dataWithContentsOfFile:filePath];
NSUInteger len = [data length];
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, [data bytes], len);

Этот код будет динамически распределять массив по правильному размеру (вы должны free(byteData), когда закончите) и копировать в него байты.

Вы также можете использовать getBytes:length:, как указано другими, если вы хотите использовать массив фиксированной длины. Это позволяет избежать malloc / free, но является менее расширяемым и более подверженным проблемам переполнения буфера, поэтому я редко использую его.

42 голосов
/ 03 декабря 2010

Вы также можете просто использовать байты там, где они есть, и приводить их к нужному вам типу.

unsigned char *bytePtr = (unsigned char *)[data bytes];
12 голосов
/ 21 апреля 2014

Уже ответил, но обобщить, чтобы помочь другим читателям:

    //Here:   NSData * fileData;
    uint8_t * bytePtr = (uint8_t  * )[fileData bytes];

    // Here, For getting individual bytes from fileData, uint8_t is used.
    // You may choose any other data type per your need, eg. uint16, int32, char, uchar, ... .
    // Make sure, fileData has atleast number of bytes that a single byte chunk would need. eg. for int32, fileData length must be > 4 bytes. Makes sense ?

    // Now, if you want to access whole data (fileData) as an array of uint8_t
    NSInteger totalData = [fileData length] / sizeof(uint8_t);

    for (int i = 0 ; i < totalData; i ++)
    {
        NSLog(@"data byte chunk : %x", bytePtr[i]);
    }
9 голосов
/ 07 апреля 2009

Подпись -[NSData bytes] является - (const void *)bytes. Вы не можете назначить указатель на массив в стеке. Если вы хотите скопировать буфер, управляемый объектом NSData, в массив, используйте -[NSData getBytes:]. Если вы хотите сделать это без копирования, не выделяйте массив; просто объявите переменную-указатель и позвольте NSData управлять памятью за вас.

2 голосов
/ 07 апреля 2009

Это связано с тем, что тип возвращаемого значения для [байтов данных] представляет собой массив типа void * c, а не Uint8 (для этого используется байт typedef).

Ошибка в том, что вы пытаетесь установить выделенный массив, когда возвращаемый тип является указателем, то вы ищете getBytes: length: call, который будет выглядеть так:

[data getBytes:&byteData length:len];

Который заполняет выделенный массив данными из объекта NSData.

0 голосов
/ 01 февраля 2018

Вот что я считаю эквивалентом Swift:

if let data = NSData(contentsOfFile: filePath) {
   let length = data.length
   let byteData = malloc(length)
   memcmp(byteData, data.bytes, length)
}
...