0

我正在尝试读取文件的前四个字节。我知道这适用于以下 C 代码:

FILE *file = fopen(URL.path.UTF8String, "rb");
uint data;
fread(&data, 4, 1, file);
NSLog(@"%u", data);

打印出来:205

我正在尝试在 Objective-C/使用 Cocoa 函数中找到等效的方法。我已经尝试了很多东西。我觉得以下内容很接近:

NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingFromURL:URL error:nil];
NSData *data2 = [fileHandle readDataOfLength:4];
NSLog(@"%@", data2);
NSLog(@"%u", (uint)data2.bytes);

这打印出来:< cd000000 >

和:1703552

正如所料,文件的前四个字节确实是 CD000000。

我假设有两件事之一导致差异(或两者兼而有之):

  1. fread 不计算 CD 后面的 0。我已经通过仅使用 fileHandle 读取 1 个字节来确认这一点,但有时这个数字会扩展超过一个字节,所以我不能像这样限制它。我是否需要手动检查传入的字节不是 00?

  2. 这与字节顺序有关。我已经尝试了许多功能,例如 CFSwapInt32BigToHost 但无法取回正确的值。如果有人能告诉我字节序如何工作/影响这一点,那就太好了。

4

3 回答 3

5

您没有取消引用数据。

NSLog(@"%u", (uint)data2.bytes); // wrong

“快速破解”版本是这样的:

NSLog(@"%u", *(uint *) data2.bytes); // hack

更强大的解决方案需要复制到某个地方的变量,以使对齐正确,但这在所有平台上都无关紧要:

uint value;
[data getBytes:&value length:sizeof(value)];
NSLog(@"%u", value);

另一种解决方案是显式逐字节读取数据,这种方式最便携,在任何平台上都没有对齐问题,在任何平台上都没有字节顺序问题:

unsigned char *p = data.bytes;
uint value = (unsigned) p[0] | ((unsigned) p[1] << 8) |
             ((unsigned) p[2] << 16) | ((unsigned) p[3] << 24);
NSLog(@"%u", value);

如您所见,我们有充分的理由避免自己将二进制数据放入文件中,而是将其留给库或使用文本格式。

这不是字节顺序的问题,因为fread()它工作正常。fread()函数和-readDataOfLength:方法都会给你相同的结果:一大块字节。

于 2013-09-16T08:09:00.140 回答
1

您尝试将 4 个字节的序列重新解释为无符号整数。这不保证适用于所有平台。仅当 sizeof(unsigned int) 等于 4 时才有效。并且仅当读取和写入的字节顺序相同时才有效。

此外,您没有使用 NSLog 正确打印标量。

于 2013-09-16T08:11:59.833 回答
-1

fread()在二进制模式下不会对你的数据做任何事情,你会得到文件中的字节。

造成这种情况的绝对是字节顺序,但我对Apple的Objective C API:s一无所知。我不明白为什么你不需要对data2对象进行指针访问,甚至(为什么没有data2.bytes失败,并且data2->bytes需要?)。

此外,文档NSData并没有说明我能找到的字节顺序。

于 2013-09-16T07:55:25.867 回答