Objective c 如何从对象c中的文件中获取字节数据
我从Objective c 如何从对象c中的文件中获取字节数据,objective-c,macos,Objective C,Macos,我从fcntl(fd,F_GLOBAL_NOCACHE,1)读取文件从磁盘而不是缓存读取文件。读取文件后,我只能获取字符串数据。现在我想在读取文件后,将文件的字节数据转换为NSMutableData。我该怎么做?提前谢谢 if (fd) { fcntl(fd, F_GLOBAL_NOCACHE, 1); NSMutableData* myData = [[NSMutableData alloc] init]; while(YES) {
fcntl(fd,F_GLOBAL_NOCACHE,1)读取文件代码>从磁盘而不是缓存读取文件。读取文件后,我只能获取字符串数据。现在我想在读取文件后,将文件的字节数据转换为NSMutableData。我该怎么做?提前谢谢
if (fd)
{
fcntl(fd, F_GLOBAL_NOCACHE, 1);
NSMutableData* myData = [[NSMutableData alloc] init];
while(YES)
{
// store the length before addition
NSUInteger previousLength = [myData length];
// increase the length so we can write more bytes
[myData increaseLengthBy:300];
// read bytes from stream directly at the end of our data
size_t len = fread([myData mutableBytes] + previousLength, 300, 1, fd);
// set data length
[myData setLength:previousLength + len];
// if end-of-file exit the loop
if (len == 0) {
break;
}
[myData appendBytes:buffer length:len];
}
// use your 'myData'
NSLog(@"dataFile: %@",myData);
[myData release];
请给我一些建议?谢谢
更新2:
现在我有另一个问题:我想直接从磁盘而不是缓存中读取文件。我使用了以下代码,但似乎不起作用,它仍然从缓存中读取:
NSString *url= [NSString stringWithFormat:@"%@/demo.abc"];
const char *c_sd_url = [url UTF8String];
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
FILE * fd = fopen(c_sd_url, "rb");
if (fd)
{
fcntl(fd, F_GLOBAL_NOCACHE, 1);
fseek(fd, 0, SEEK_END);
long sz = ftell(fd);
fseek(fd, 0, SEEK_SET);
char *buf = malloc(sz);
NSLog(@"before %s",buf);
assert(buf != NULL);
assert(fread(buf, sz, 1, fd) == 1);
NSLog(@"after %s",buf);
NSMutableData *data= [NSMutableData dataWithBytesNoCopy:buf length:sz freeWhenDone:YES];
NSLog(@"%@",data);
}
我使用了fcntl(fd,F_GLOBAL_NOCACHE,1)代码>在fopen()之后。请给我任何建议。非常感谢我想,热舔是正确的,您可能只想使用-[NSData DATA WITH CONTENTS OFFILE:
,但如果您想使用C级API,您可以:
#define MY_BUFFER_SIZE 1024
FILE * fd = fopen(c_sd_url, "rb");
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
char buffer[MY_BUFFER_SIZE];
if (fd)
{
fcntl(fd, F_GLOBAL_NOCACHE, 1);
// if you can predict the capacity it's better for performance
NSMutableData* myData = [NSMutableData dataWithCapacity:1024];
while(fgets(buffer, MY_BUFFER_SIZE, fd) != NULL)
{
[myData appendBytes:buffer length:strlen(buffer)];
}
}
// use your 'myData'
[pool release];
更新:以避免缓冲区数据的无用复制,并遵循H2CO3的注释:
最好避免将数据写入缓冲区,然后将其复制到NSMutableData,我们可以使用-[NSData mutableBytes]
直接访问底层C结构。另外,H2CO3完全正确,使用fread
会更好,因为它提供了读取字节的长度
#define MY_BUFFER_SIZE 1024
FILE * fd = fopen(c_sd_url, "rb");
if (fd)
{
fcntl(fd, F_GLOBAL_NOCACHE, 1);
// if you can predict the capacity it's better for performance
NSMutableData* myData = [[NSMutableData alloc] init];
while(YES)
{
// store the length before addition
NSUInteger previousLength = [myData length];
// increase the length so we can write more bytes
[myData increaseLengthBy:MY_BUFFER_SIZE];
// read bytes from stream directly at the end of our data
size_t len = fread([myData mutableBytes] + previousLength, 1, MY_BUFFER_SIZE, fd);
// set data length
[myData setLength:previousLength + len];
// if end-of-file exit the loop
if (len == 0) {
break;
}
}
// use your 'myData'
NSLog(@"myData: %@", [[NSString alloc] initWithData:myData encoding:NSASCIIStringEncoding]);
[myData release];
}
如果要终止NSData,只需在末尾添加:
[myData appendBytes:"\0" length:1];
祝你好运;) 标准保证C中的字符至少为1字节
因此,您可以将char*
视为具有适当大小乘法的字节数组,并将其传递给-[NSData initWithBytes:length:][/code>方法
char buffer[300];
NSData* data0 = [[NSData alloc] initWithBytes:buffer length:300 * sizeof(char)];
有几种初始化方法,请根据需要检查它们。有关过程样式的使用,请参见NSMutableData
或者你可以像@HotLicks所说的那样使用NSData
方法
NSData* data0 = [NSData dataWithContentsOfFile:@"somefile" options:NSDataReadingUncached error:NULL];
最简单的方法是使用NSData DATA WITH CONTENTS OFFILE。如果使用它,它可以从磁盘而不是缓存中读取文件?@Huynhhttkt您似乎没有读取该方法的文档,这是不好的。非常感谢,但如果终端上有“\0”。如何获得它?我刚刚更新了我的答案,它将更适合您的需要+它更优化。无论如何,如果您想获得\0终止的数据,只需在末尾添加[myData appendBytes:“\0”长度:1]
。@MichaMazaheri Welp。以前的版本更好。我想说的是,你不需要一个循环。您读入一个足够大的缓冲区一次,然后用它初始化数据对象@H2CO3哦,好的!我没有注意到变量的名称文件大小
。我想这一切都取决于文件的大小。。。但一般来说,这是一种不好的做法,因为您可能事先不知道文件大小(或者您之前可能会检查它)。@Huynhhttkt刚刚测试了我的第二个代码,它对我来说很好。我认为您的问题在于,您只是将一个NSData
传递给NSLog
,这使得它以十六进制表示形式打印出来。如果要显示为“普通”字符串,则需要先将其转换为NSString
。刚刚为您更新了最后一段代码。谢谢,但我使用了NSData*data0=[[NSData alloc]initWithBytes:buffer length:300*sizeof(char)];,它返回的数据与原始文件不同吗?为什么?它们有什么不同?我认为这是其他函数上的一些错误,例如fcntl
或fgets
。-initWithBytes~
方法仅处理已加载到内存中的字节数组,而与加载进程本身完全无关。“C中的char
标准保证至少为8位。”-不,不是。