Objective-C / Cocoa相当于fread

时间:2013-09-16 07:50:01

标签: objective-c c cocoa

我正在尝试读取文件的前四个字节。我知道这可以正常使用以下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,但无法恢复正确的值。如果有人能够告诉我关于字节顺序如何起作用/效果,那将是很棒的。

3 个答案:

答案 0 :(得分: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:方法都会给你相同的结果:一块字节。

答案 1 :(得分:1)

您尝试将4个字节的序列重新解释为unsigned int。这不能保证适用于所有平台。只有当sizeof(unsigned int)等于4时才会起作用。只有在读写字节顺序相同的情况下才会起作用。

此外,您不能使用NSLog正确打印标量。

答案 2 :(得分:-1)

二进制模式下的

fread()不会对您的数据执行任何操作,您将获得文件中的字节。

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

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