如何在iPhone中将NSData转换为字节数组?

51

我想将 NSData 转换为字节数组,因此我编写了以下代码:

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

但是最后一行代码弹出一个错误,显示“赋值时类型不兼容”。那么将数据转换为字节数组的正确方法是什么?

6个回答

63

你不能使用变量来声明一个数组,所以 Byte byteData[len]; 是无效的。如果你想要从指针中复制数据,你需要使用memcpy(它将遍历指针指向的数据并复制每个字节,直到指定长度为止)。

尝试:

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

这段代码将动态分配正确大小的数组(完成后必须free(byteData)),并将字节复制到其中。

如果您想使用固定长度的数组,也可以使用getBytes:length:,如其他人所示。这避免了malloc/free,但可扩展性较差且更容易发生缓冲区溢出问题,因此我很少使用它。


1
Byte byteData = malloc(len); 弹出一个警告,说“初始化使整数从指针转换而来,没有强制转换”。而byteData最终成为一个字节变量,而不是一个字节数组。对此有什么想法吗? - Chilly Zhong
代码中有一个小错别字,现在应该按照Matt的意图正常工作了。 - Jason Coco
1
@matt Gallagher:它可以正常工作,但是这种转换会造成一些延迟。如何减少延迟...有什么想法吗???? - Asta ni enohpi
1
Byte byteData[len] 可以在 Clang 和 GCC 中使用。这是有效的 C 语言(C 支持可变长度数组),因此也是有效的 Objective-C 语言。 - zneak
当我使用它时,它变成了失联设备。原因是什么? - Jungwon
显示剩余4条评论

43

你也可以直接使用它们所在的字节,将它们转换为您需要的类型。

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

这样做会出现“变量大小的对象可能无法初始化”的错误。 - Żabojad
1
测试再次表明,只有数据的第一个字节将被复制到bytePtr中:bytePtr [1],bytePtr [2]等都包含0; - Elise van Looij

16

已经回答过了,但为了帮助其他读者更好地理解:

    //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]);
    }

10
-[NSData bytes] 的签名是 - (const void *)bytes。你不能将指针分配给堆栈上的数组。如果你想将 NSData 对象管理的缓冲区复制到数组中,请使用 -[NSData getBytes:]。如果你想在没有复制的情况下完成它,则不要分配一个数组;只需声明一个指针变量,让 NSData 为你管理内存即可。

在我添加了 [data getBytes:byteData length:len]; 之后,byteData 变成了无效的。可能出了什么问题? - Chilly Zhong
尝试打印NSData并查看是否匹配;然后检查长度并确保它看起来像您期望的那样。如果数据是字符串,您还可以尝试-[NSString stringWithContentsOfFile]。 - Nicholas Riley
我找到了问题所在:长度不应该是一个变量。它应该是Byte byteData [255]; - Chilly Zhong
1
最近Java用的太多了。 :-) 很高兴你解决了它。 - Nicholas Riley

2
那是因为[data bytes]的返回类型是void* C风格数组,而不是Uint8(Byte的typedef类型)。错误是因为你试图设置一个分配的数组,但返回值是指针类型。你要找的是getBytes:length:调用,它看起来像:
[data getBytes:&byteData length:len];

这将使用NSData对象中的数据填充您已分配的数组。


byteData 是无效的。可能有什么问题? - Chilly Zhong
@ChillyZhong 尝试指定byteData的大小,例如 uint8_t *cipherBuffer[16],然后删除&并使用NSLog(@"%s", (char *)byteData); - Mazen Kasser

-1

以下是我认为等价于Swift的内容:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接