如何从对象c中的文件中获取字节数据

时间:2013-08-26 03:47:29

标签: 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)
    {

        // 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);。请给我任何建议。非常感谢

2 个答案:

答案 0 :(得分:1)

C中的

char至少按标准保证为1字节。

What is an unsigned char?

因此,您可以将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];
祝你好运;)