Objective-C/Cocoa相当于fread

Chr*_*eld 0 c cocoa objective-c

我正在尝试读取文件的前四个字节.我知道这可以正常使用以下C代码:

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

打印出来:205

我试图在Objective-C/Cocoa函数中找到相同的方法.我尝试过很多东西.我觉得以下是接近的:

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

这打印出:<cd000000>

并且:1703552

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

我假设有两个因素导致差异(或两者):

  1. fread不计算CD之后的0.我已经通过fileHandle读取1个字节来证实了这一点,但有时这个数字会扩展到大于一个字节,因此我不能像这样限制它.我是否需要手动检查进来的字节不是00?

  2. 这与字节序有关.我已经尝试了许多功能,如CFSwapInt32BigToHost,但无法恢复正确的值.如果任何人都能告诉我关于字节序如何工作/影响这将是很好的.

Die*_*Epp 5

您没有取消引用数据.

NSLog(@"%u", (uint)data2.bytes); // wrong
Run Code Online (Sandbox Code Playgroud)

"快速入侵"版本是这样的:

NSLog(@"%u", *(uint *) data2.bytes); // hack
Run Code Online (Sandbox Code Playgroud)

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

uint value;
[data getBytes:&value length:sizeof(value)];
NSLog(@"%u", value);
Run Code Online (Sandbox Code Playgroud)

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

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);
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我们有充分的理由避免将二进制数据放入文件中,并将其留给库或使用文本格式.

这不是字节顺序的问题,因为fread()它正常工作.该fread()函数和-readDataOfLength:方法都将得到相同的结果:字节块.