2009-04-07 35 views
42

Tôi muốn chuyển đổi NSData đến một mảng byte, vì vậy tôi viết đoạn mã sau:Làm thế nào để chuyển đổi NSData thành mảng byte trong iPhone?

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

Nhưng dòng cuối cùng của mã bật lên một lỗi nói rằng "loại không phù hợp trong chuyển nhượng". Cách chính xác để chuyển đổi dữ liệu thành mảng byte là gì?

Trả lời

56

Bạn không thể khai báo mảng bằng biến số để Byte byteData[len]; không hoạt động. Nếu bạn muốn sao chép dữ liệu từ một con trỏ, bạn cũng cần phải memcpy (mà sẽ đi qua các dữ liệu được trỏ đến bởi con trỏ và sao chép từng byte lên đến một chiều dài quy định).

Hãy thử:

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

Mã này sẽ tự động phân bổ mảng với kích thước chính xác (bạn phải free(byteData) khi bạn đã hoàn tất) và sao chép các byte vào nó.

Bạn cũng có thể sử dụng getBytes:length: như được chỉ định bởi những người khác nếu bạn muốn sử dụng một mảng chiều dài cố định. Điều này tránh malloc/miễn phí nhưng ít mở rộng và dễ bị các vấn đề tràn bộ nhớ đệm vì vậy tôi hiếm khi sử dụng nó.

+1

Byte byteData = malloc (len); bật lên một cảnh báo nói rằng "khởi tạo làm cho interger từ con trỏ mà không có một diễn viên". Và byteData hóa ra là một biến byte, không phải là một mảng byte. Bất kỳ ý tưởng về điều này? –

+0

Có một lỗi đánh máy nhỏ trong mã, nó sẽ làm việc ngay bây giờ như mờ dự định. –

+0

Có. Tham số thứ hai của memcpy phải là [byte dữ liệu]. –

9

Chữ ký của -[NSData bytes]- (const void *)bytes. Bạn không thể gán một con trỏ cho một mảng trên ngăn xếp. Nếu bạn muốn sao chép bộ đệm được đối tượng NSData quản lý vào mảng, hãy sử dụng -[NSData getBytes:]. Nếu bạn muốn làm điều đó mà không cần sao chép, sau đó không phân bổ một mảng; chỉ cần khai báo một biến con trỏ và để NSData quản lý bộ nhớ cho bạn.

+0

Sau khi tôi thêm [getBytes dữ liệu: chiều dài byteData: len]; byteData hóa ra là không hợp lệ. Rắc rối có thể là cái gì? –

+0

Thử in NSData và xem nó có phù hợp hay không; sau đó kiểm tra độ dài và chắc chắn rằng nó trông giống như những gì bạn đang mong đợi. Nếu dữ liệu là một chuỗi, bạn cũng có thể thử - [NSString stringWithContentsOfFile]. –

+0

Tôi phát hiện ra sự cố: độ dài không được là biến. Nó phải là Byte byteData [255]; –

2

Đó là vì loại trả về cho [byte dữ liệu] là một mảng kiểu ô trống * c, không phải là Uint8 (đó là Byte là typedef cho).

Lỗi này là bởi vì bạn đang cố gắng để thiết lập một mảng phân bổ khi sự trở lại là một loại con trỏ, những gì bạn đang tìm kiếm là getBytes: chiều dài: gọi đó sẽ như thế nào:

[data getBytes:&byteData length:len]; 

nào lấp đầy mảng bạn đã phân bổ với dữ liệu từ đối tượng NSData.

+0

byteData không hợp lệ. Rắc rối có thể là cái gì? –

+0

@ChillyZhong cố gắng chỉ định kích thước byteData, ví dụ 'uint8_t * cipherBuffer [16]' rồi xóa '&' và NSLog (@ "% s", (char *) byteData); –

41

Bạn cũng có thể chỉ sử dụng byte ở vị trí hiện tại của chúng, truyền chúng sang loại bạn cần.

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

Việc làm này, tôi nhận được một "đối tượng biến kích thước có thể không được khởi tạo" lỗi –

+0

Một lần nữa, xét nghiệm cho thấy rằng chỉ có byte đầu tiên của dữ liệu sẽ được sao chép vào bytePtr: bytePtr [1], bytePtr [2], vv chứa 0 ; –

11

Đã trả lời, nhưng có thể khái quát để giúp độc giả khác:

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

Đây là những gì tôi tin là tương đương với Swift:

if let data = NSData(contentsOfFile: filePath) { 
    let length = data.length 
    let byteData = malloc(length) 
    memcmp(byteData, data.bytes, length) 
} 
Các vấn đề liên quan