2009-04-07 15 views
42

chcę przekonwertować NSData do tablicy bajtów, więc napisać następujący kod:Jak przekonwertować NSData na tablicę bajtów w telefonie iPhone?

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

ale ostatni wiersz kodu wyskakuje błąd powiedzenie „niezgodne typy w przydziale”. Jaki jest prawidłowy sposób konwertowania danych na tablicę bajtów?

Odpowiedz

56

Nie można zadeklarować tablicy przy użyciu zmiennej, więc Byte byteData[len]; nie będzie działać. Jeśli chcesz skopiować dane ze wskaźnika, musisz również memcpy (który przejdzie przez dane wskazywane przez wskaźnik i skopiować każdy bajt do określonej długości).

Spróbuj:

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

Kod ten będzie dynamicznie przydzielać tablicę do odpowiedniego rozmiaru (musisz free(byteData) kiedy skończysz) i kopiowanie bajtów do niego.

Możesz również użyć getBytes:length:, jak wskazali inni, jeśli chcesz użyć tablicy o stałej długości. Pozwala to uniknąć malloc/free, ale jest mniej rozszerzalne i bardziej podatne na problemy z przepełnieniem bufora, dlatego rzadko go używam.

+1

Byte byteData = malloc (len); wyskakuje ostrzeżenie z informacją, że "inicjalizacja łączy się ze wskaźnikiem bez rzutowania". A bajtData okazuje się być zmienną bajtową, a nie tablicą bajtową. Wszelkie pomysły na ten temat? –

+0

W kodzie pojawiła się mała literówka, teraz powinna działać tak, jak powinna. –

+0

Tak. Drugim parametrem memcpy powinno być [bajty danych]. –

9

Podpis -[NSData bytes] to - (const void *)bytes. Nie można przypisać wskaźnika do tablicy na stosie. Jeśli chcesz skopiować bufor zarządzany przez obiekt NSData do tablicy, użyj -[NSData getBytes:]. Jeśli chcesz to zrobić bez kopiowania, nie przydzielaj tablicy; po prostu zadeklaruj zmienną wskaźnika i pozwól, aby NSData zarządzała pamięcią.

+0

Po dodam [getBytes danych: długość byteData: len]; bajtData okazuje się nieważny. Co może być problemem? –

+0

Spróbuj wydrukować NSData i sprawdź, czy pasuje; następnie sprawdź długość i upewnij się, że wygląda na to, czego oczekujesz. Jeśli dane są ciągami, możesz również spróbować - [łańcuch NSString z ContentContent]. –

+0

Dowiedziałem się, że problem: długość nie powinna być zmienną. Powinien to być bajt bajtów [255]; –

2

Dzieje się tak dlatego, że typem powrotu dla [danych bajtów] jest pusta * tablica w stylu c, a nie Uint8 (co jest tym, co Byte jest typem for).

Błąd dlatego staramy się ustawić przydzielonej tablicy, gdy zwrot jest rodzajem wskaźnika, co szukasz jest getBytes: długość: zadzwoń który wyglądałby następująco:

[data getBytes:&byteData length:len]; 

który wypełnia tablica, którą przydzieliłeś z danymi z obiektu NSData.

+0

BajtData jest nieprawidłowy. Co może być problemem? –

+0

@ChillyZhong spróbuj określić rozmiar byteData na przykład 'uint8_t * cipherBuffer [16]' następnie usuń '&' i NSLog (@ "% s", (char *) byteData); –

41

Można również po prostu użyć bajtów tam, gdzie są, przesyłając je do potrzebnego typu.

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

W ten sposób pojawia się błąd "Nie można zainicjować obiektu o zmiennej wielkości" –

+0

Ponownie, testy pokazują, że tylko pierwszy bajt danych zostanie skopiowany do bytePtr: bytePtr [1], bytePtr [2] itd. Zawierają 0 ; –

11

już odpowiedział, ale uogólniać, aby pomóc innym czytelników:

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

Oto co wierzę, jest Swift równoważne:

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