Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 如何从对象c中的文件中获取字节数据_Objective C_Macos - Fatal编程技术网

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位。”-不,不是。