我从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];
请给我建议?感谢
UPDATE2: 现在我有另一个问题:我想从磁盘直接读取文件而不是从Cache。我使用下面的代码,但它似乎不起作用,它仍然从缓存中读取:
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);
}
我在fopen()之后使用了fcntl(fd, F_GLOBAL_NOCACHE, 1);
。请给我任何建议。非常感谢
答案 0 :(得分:1)
char
至少按标准保证为1字节。
因此,您可以将char*
视为具有适当大小乘法的字节数组,并且可以将其传递给-[NSData initWithBytes:length:]
方法。
char buffer[300];
NSData* data0 = [[NSData alloc] initWithBytes:buffer length:300 * sizeof(char)];
有几种初始化方法,因此请根据您的需要进行检查。有关程序样式的使用,请参阅NSMutableData
。
或者您可以使用NSData
方法,就像@HotLicks所说的那样。
NSData* data0 = [NSData dataWithContentsOfFile:@"somefile" options:NSDataReadingUncached error:NULL];
答案 1 :(得分:0)
我猜 Hot Licks 是对的,你可能只想使用-[NSData dataWithContentsOfFile:]
,但是如果你想使用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];
已更新:,以避免无用的buffer
数据副本,并遵循 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];
}
如果你想要一个\0
终止的NSData,只需在最后添加:
[myData appendBytes:"\0" length:1];
祝你好运;)