2009-04-07 15 views
42

voglio convertire NSData a un array di byte, quindi scrivere il codice seguente:Come convertire NSData in array di byte in iPhone?

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

Ma l'ultima riga di codice si solleva un errore che dice "tipi incompatibili di assegnazione". Qual è il modo corretto di convertire i dati in serie di byte?

risposta

56

Non è possibile dichiarare un array utilizzando una variabile, pertanto Byte byteData[len]; non funzionerà. Se vuoi copiare i dati da un puntatore, devi anche memcpy (che passerà attraverso i dati puntati dal puntatore e copierà ogni byte fino a una lunghezza specificata).

Prova:

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

Questo codice allocare dinamicamente la matrice per il formato corretto (è necessario free(byteData) quando hai finito) e copiare i byte in esso.

È anche possibile utilizzare getBytes:length: come indicato da altri se si desidera utilizzare una matrice di lunghezza fissa. Questo evita malloc/free ma è meno estensibile e più incline a bufferare i problemi di overflow quindi raramente lo uso mai.

+1

byte byteData = malloc (len); appare un avvertimento che dice "l'inizializzazione rende interger dal puntatore senza cast". E byteData risulta essere una variabile di byte, non una matrice di byte. Qualche idea su questo? –

+0

C'era un piccolo refuso nel codice, dovrebbe funzionare ora come previsto. –

+0

Sì. Il secondo parametro di memcpy dovrebbe essere [data byte]. –

9

La firma di -[NSData bytes] è - (const void *)bytes. Non è possibile assegnare un puntatore a un array nello stack. Se si desidera copiare il buffer gestito dall'oggetto NSData nell'array, utilizzare -[NSData getBytes:]. Se vuoi farlo senza copiare, non assegnare un array; basta dichiarare una variabile puntatore e lasciare che NSData gestisca la memoria per te.

+0

Dopo aggiungo [getBytes dati: lunghezza byteData: len]; il byteData risulta non valido. Quale potrebbe essere il problema? –

+0

Provare a stampare NSData e vedere se corrisponde; quindi controlla la lunghezza e assicurati che assomigli a quello che ti aspetti. Se i dati sono una stringa, puoi anche provare - [NSString stringWithContentsOfFile]. –

+0

Ho scoperto il problema: la lunghezza non dovrebbe essere una variabile. Dovrebbe essere Byte byteData [255]; –

2

Questo perché il tipo di ritorno per [data byte] è un array * c-style void, non un Uint8 (che è ciò che Byte è un typedef per).

L'errore è dovuto al fatto che si sta tentando di impostare una matrice allocata quando il rendimento è un tipo di puntatore, ciò che si sta cercando è la getBytes: lunghezza: chiamare, che sarebbe simile:

[data getBytes:&byteData length:len]; 

che riempie l'array che hai assegnato con i dati dall'oggetto NSData.

+0

Il byteData non è valido. Quale potrebbe essere il problema? –

+0

@ChillyZhong prova a specificare la dimensione byteData per esempio 'uint8_t * cipherBuffer [16]' quindi rimuovi '&' e NSLog (@ "% s", (char *) byteData); –

41

Si potrebbe anche solo usare i byte dove sono, gettandoli nel tipo desiderato.

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

In questo modo, viene visualizzato un errore "L'oggetto di dimensioni variabili potrebbe non essere inizializzato" errore –

+0

Ancora, i test mostrano che solo il primo byte di dati verrà copiato in bytePtr: bytePtr [1], bytePtr [2], ecc. Contengono 0 ; –

11

già risposto, ma a generalizzare per aiutare altri lettori:

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

Ecco quello che credo è l'equivalente Swift:

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