Reputation: 19
I read file from fcntl(fd, F_GLOBAL_NOCACHE, 1);
to read file from Disk not from Cache. After reading file, i can only get string data. Now i want to after reading file, i get byte data of file to NSMutableData. How can i do that? Thanks in advance.
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];
Please give me suggestions? thanks
UPDATE2: Now i have another problem: i want to read file direct from disk not from Cache. I used below code but it seem not work, it still read from 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);
}
I used fcntl(fd, F_GLOBAL_NOCACHE, 1);
after fopen(). Please give me any suggestion. Thanks much
Upvotes: 0
Views: 6087
Reputation: 3481
I guess Hot Licks is right, you probably want to simply use -[NSData dataWithContentsOfFile:]
, but in the case you want to use C level APIs, you can do:
#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];
Updated: to avoid useless copy of buffer
data, and following H2CO3's comment:
It's better to avoid to write data to a buffer and then copy it to the NSMutableData, we can use -[NSData mutableBytes]
to access directly the underlying C structure. Also, H2CO3 is completely right, using fread
is much better since it gives us the length of the bytes read.
#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];
}
If you want to have a \0
terminated NSData, just add at the end:
[myData appendBytes:"\0" length:1];
Good luck ;)
Upvotes: 1
Reputation: 85975
char
in C is guaranteed to be 1 byte at least by standard.
So you can treat char*
as byte-array with proper size multiplication, and you can pass it to -[NSData initWithBytes:length:]
method.
char buffer[300];
NSData* data0 = [[NSData alloc] initWithBytes:buffer length:300 * sizeof(char)];
There're several initializer methods, so check them out for your needs. See NSMutableData
for procedural style use.
Or you can use NSData
method as like @HotLicks said.
NSData* data0 = [NSData dataWithContentsOfFile:@"somefile" options:NSDataReadingUncached error:NULL];
Upvotes: 1