2009-04-07 15 views
42

Quiero cambiar NSData a una matriz de bytes, por lo que escribir el siguiente código:¿Cómo convertir NSData a matriz de bytes en iPhone?

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

Pero la última línea de código aparece un error que dice "tipos incompatibles en la asignación". ¿Cuál es la forma correcta de convertir los datos a una matriz de bytes?

Respuesta

56

No puede declarar una matriz utilizando una variable para que Byte byteData[len]; no funcione. Si desea copiar los datos de un puntero, también necesita memcpy (que pasará por los datos apuntados por el puntero y copiará cada byte hasta una longitud específica).

Probar:

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

Este código será asignar dinámicamente la matriz al tamaño correcto (debe free(byteData) cuando haya terminado) y copiar los bytes en él.

También puede usar getBytes:length: como lo indiquen otros si desea utilizar una matriz de longitud fija. Esto evita malloc/free pero es menos extensible y más propenso a problemas de desbordamiento de buffer por lo que rara vez lo uso.

+1

Byte byteData = malloc (len); aparece una advertencia que dice "la inicialización hace interger desde el puntero sin un molde". Y byteData resulta ser una variable de bytes, no una matriz de bytes. Alguna idea sobre esto? –

+0

Había un pequeño error ortográfico en el código, debería funcionar ahora como pretendía Matt. –

+0

Sí. El segundo parámetro de memcpy debe ser [data bytes]. –

9

La firma de -[NSData bytes] es - (const void *)bytes. No puede asignar un puntero a una matriz en la pila. Si desea copiar el búfer administrado por el objeto NSData en la matriz, use -[NSData getBytes:]. Si desea hacerlo sin copiar, no asigne una matriz; solo declare una variable de puntero y deje que NSData administre la memoria por usted.

+0

Después agrego [getBytes datos: Longitud byteData: len]; byteData resulta ser inválido. ¿Cuál podría ser el problema? –

+0

Intenta imprimir NSData y ver si coincide; luego verifica la duración y asegúrate de que se vea como lo que estás esperando. Si los datos son una cadena, también puede intentar - [NSString stringWithContentsOfFile]. –

+0

Descubro el problema: la longitud no debe ser una variable. Debería ser ByteDateData [255]; –

2

Esto se debe a que el tipo de retorno para [data bytes] es una matriz void * c-style, no un Uint8 (que es de lo que Byte es un typedef).

El error se debe a que usted está tratando de establecer una serie asignado cuando el retorno es un tipo de puntero, lo que busca es la getBytes: longitud: llamar a la cual se vería así:

[data getBytes:&byteData length:len]; 

que llena la matriz que ha asignado con los datos del objeto NSData.

+0

ByteData no es válido. ¿Cuál podría ser el problema? –

+0

@ChillyZhong intenta especificar el tamaño de byteData por ejemplo 'uint8_t * cipherBuffer [16]' luego elimina el '&' y NSLog (@ "% s", (char *) byteData); –

41

También puede utilizar los bytes en el lugar en el que están, fundiéndolos al tipo que necesita.

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

Al hacer esto, aparece el error "No se puede inicializar el objeto de tamaño variable" –

+0

De nuevo, las pruebas muestran que solo el primer byte de datos se copiará en bytePtr: bytePtr [1], bytePtr [2], etc. contienen 0 ; –

11

ya ha respondido, pero generalizar para ayudar a otros lectores:

//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

Esto es lo que creo que es el equivalente Swift:

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