Как преобразовать NSData в массив байтов в iPhone?
-
05-09-2019 - |
Вопрос
Я хочу обратить NSData
в массив байтов, поэтому я пишу следующий код:
NSData *data = [NSData dataWithContentsOfFile:filePath];
int len = [data length];
Byte byteData[len];
byteData = [data bytes];
Но в последней строке кода появляется сообщение об ошибке "несовместимые типы в присваивании".Каков тогда правильный способ преобразовать данные в массив байтов?
Решение
Вы не можете объявить массив, используя переменную, поэтому 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, но менее расширяемо и более подвержено проблемам с переполнением буфера, поэтому я редко им пользуюсь.
Другие советы
Вы также могли бы просто использовать байты там, где они есть, приведя их к нужному вам типу.
unsigned char *bytePtr = (unsigned char *)[data bytes];
Уже ответил, но хочу обобщить, чтобы помочь другим читателям:
//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]);
}
Подпись -[NSData bytes]
является - (const void *)bytes
.Вы не можете назначить указатель на массив в стеке.Если вы хотите скопировать буфер, управляемый NSData
объект в массив, используйте -[NSData getBytes:]
.Если вы хотите сделать это без копирования, то не выделяйте массив;просто объявите переменную-указатель и позвольте NSData
управляйте памятью за вас.
Это потому, что возвращаемый тип для [байтов данных] представляет собой массив в стиле void * c, а не Uint8 (для которого Byte является typedef).
Ошибка заключается в том, что вы пытаетесь установить выделенный массив, когда возвращаемый тип является типом указателя, то, что вы ищете, - это getBytes:length:вызов, который выглядел бы как:
[data getBytes:&byteData length:len];
Который заполняет выделенный вами массив данными из объекта NSData.
Вот то, что, по моему мнению, является эквивалентом Swift:
if let data = NSData(contentsOfFile: filePath) {
let length = data.length
let byteData = malloc(length)
memcmp(byteData, data.bytes, length)
}