2011-02-01 35 views
7

Tôi có một mục NSData đang nắm giữ một loạt các int. Làm thế nào để tôi đi về nhận chúng ra và vào một NSArray?Obj-C Làm thế nào để chuyển đổi NSData thành một mảng ints?

Cấu trúc bộ nhớ trong NSData là int 32 bit theo thứ tự nhỏ, một bên phải theo thứ tự khác.

Xin lỗi vì câu hỏi cơ bản, nhưng vẫn tìm hiểu cách thức hoạt động của obj-c :)

Trả lời

13

Bạn có thể sử dụng các chức năng quy định tại để đối phó với endian. Bên cạnh đó, điều này thực sự chỉ là vấn đề lấy bộ đệm byte và lặp lại nó.

// returns an NSArray containing NSNumbers from an NSData 
// the NSData contains a series of 32-bit little-endian ints 
NSArray *arrayFromData(NSData *data) { 
    void *bytes = [data bytes]; 
    NSMutableArray *ary = [NSMutableArray array]; 
    for (NSUInteger i = 0; i < [data length]; i += sizeof(int32_t)) { 
     int32_t elem = OSReadLittleInt32(bytes, i); 
     [ary addObject:[NSNumber numberWithInt:elem]]; 
    } 
    return ary; 
} 
+0

Tôi đã sử dụng mã này trong dự án của mình và nó hoạt động tốt. – Justin808

0

Một giải pháp có thể có bên dưới. Để xem xét tính xác thực, hãy tra cứu tham chiếu Core Endian trong bộ tài liệu XCode (có thể bạn sẽ sử dụng EndianS32_LtoN (32 bit litte endian đến native endianness)).

int mem[]= {0x01, 0x02, 0x03, 0x04, 0xff}; 


NSData * data = [NSData dataWithBytes:mem length:sizeof(mem)*sizeof(int)]; 
NSMutableArray * ar = [NSMutableArray arrayWithCapacity:10]; 

/* read ints out of the data and add them to the array, one at a time */ 
int idx=0; 
for(;idx<[data length]/sizeof(int);idx+=sizeof(int)) 
     [ar addObject:[NSNumber numberWithInt:*(int *)([data bytes] + idx)]]; 

NSLog(@"Array:%@", ar); 
+0

Ý của bạn là int32_t? Mã này có bị hỏng trên x64 không? –

+1

Tôi nghĩ 'int' vẫn dài 4 byte trên x86_64. Đó là 'long' khớp với kích thước chữ. Hoặc cụ thể hơn, 'int' phụ thuộc vào trình biên dịch, nhưng trong gcc và clang trên tất cả các kiến ​​trúc của Cocoa, nó sẽ là 4 byte. Tuy nhiên, 'int32_t' sẽ phù hợp hơn (và bạn có thể thấy những gì tôi đã sử dụng trong câu trả lời của mình). –

+0

Tôi đã viết mã trên x86_64 - int vẫn dài 4 byte. Nhưng cả hai đều đúng, int32_t là phù hợp hơn. – diciu

2

Âm thanh như có những cách sạch hơn để làm những gì bạn đang cố gắng để làm, nhưng điều này sẽ làm việc:

NSData *data = ...; // Initialized earlier 
int *values = [data bytes], cnt = [data length]/sizeof(int); 
for (int i = 0; i < cnt; ++i) 
    NSLog(@"%d\n", values[i]); 
1

Câu trả lời này rất giống với các câu trả lời khác ở trên, nhưng tôi thấy nó có vai trò hướng dẫn khi truyền các byte NSData trở lại mảng int32_t []. Mã này hoạt động chính xác trên một bộ vi xử lý nhỏ (x64 trong trường hợp của tôi) nhưng sẽ là âm thầm sai trên big-endian (PPC) vì biểu diễn byte sẽ là big-endian.

int32_t raw_data[] = {0,1,2,3,4,5,6,7,8,9,10}; 
printf("raw_data has %d elements\n", sizeof(raw_data)/sizeof(*raw_data)); 
NSData *data = [NSData dataWithBytes:(void*)raw_data length:sizeof(raw_data)]; 
printf("data has %d bytes\n", [data length]); 
int32_t *int_data_out = (int32_t*) [data bytes]; 
for (int i=0; i<[data length]/4; ++i) 
    printf("int %d = %d\n", i, int_data_out[i]); 
[data release]; 
Các vấn đề liên quan