2009-04-07 4 views
42

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

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

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

ответ

56

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

Try:

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, но является менее расширяемым и более подверженным проблемам с переполнением буфера, поэтому я редко его использую.

+1

Byte byteData = malloc (len); выдает предупреждение о том, что «инициализация делает interger из указателя без приведения». И byteData оказывается байтовой переменной, а не байтовым массивом. Есть идеи об этом? –

+0

В коде была небольшая опечатка, теперь она должна работать как матовая. –

+0

Да. Второй параметр memcpy должен быть [data bytes]. –

9

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

+0

После того как я добавить [GetBytes данные: длина byteData: Len]; byteData оказывается недопустимым. Что может быть проблемой? –

+0

Попробуйте распечатать NSData и посмотреть, совпадает ли это; затем проверьте длину и убедитесь, что она похожа на то, что вы ожидаете. Если данные являются строкой, вы также можете попробовать - [NSString stringWithContentsOfFile]. –

+0

Я выясняю проблему: длина не должна быть переменной. Он должен быть Byte byteData [255]; –

2

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

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

[data getBytes:&byteData length:len]; 

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

+0

Недопустимый байтовый каталог. Что может быть проблемой? –

+0

@ChillyZhong попробуйте указать размер байта данных, например 'uint8_t * cipherBuffer [16]', затем удалите '&' и NSLog (@ "% s", (char *) byteData); –

41

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

unsigned char *bytePtr = (unsigned char *)[data bytes]; 
+0

Выполняя это, я получаю сообщение об ошибке «Объект переменной размера не может быть инициализирован» –

+0

Опять же, тесты показывают, что только первый байт данных будет скопирован в bytePtr: bytePtr [1], bytePtr [2] и т. Д. Содержат 0 ; –

11

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

//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]); 
    } 
0

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

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