我无法理解为dispatch_io_read函数调用提供给数据应用程序的偏移量变量。我看到documentation声称偏移量是与数据对象基数的逻辑偏移量。查看dispatch_data_apply函数的source code确认此变量始终从0开始,第一次申请数据块,然后只是范围长度的总和。
我想我当时并不了解这个变量的用途。我最初认为这是整个阅读的偏移量,但事实并非如此。看来你必须跟踪读取的字节数和偏移量,才能在libdispatch中实际正确读取。
// Outside the dispatch_io_read handler...
char * currBufferPosition = destinationBuffer;
// Inside the dispatch_io_read handler...
dispatch_io_read(channel, fileOffset, bytesRequested, queue, ^(bool done, dispatch_data_t data, int error) {
// Note: Real code would handle error variable.
dispatch_data_apply(data, ^bool(dispatch_data_t region, size_t offset, const void * buffer, size_t size) {
memcpy(currBufferPosition, buffer, size);
currBufferPosition += size;
return true;
});
});
我的问题是:这是使用dispatch_data_apply返回的数据的正确方法吗?如果是这样,传递给应用程序处理程序的偏移量变量的目的是什么?这篇文档对我来说似乎并不清楚。
答案 0 :(得分:0)
dispatch_data_t
是一个字节序列。字节可以存储在多个非连续的字节数组中。例如,字节0-6可以存储在一个数组中,然后字节7-12存储在内存中其他位置的单独数组中。
为了提高效率,dispatch_data_apply
函数允许您就地迭代这些数组(不复制数据)。在每次调用“applier”时,您会收到指向buffer
参数中的一个底层存储阵列的指针。 size
参数告诉你这个特定数组中有多少字节,offset
参数告诉你这个特定数组的第一个字节是如何(逻辑上)远离整个{{的第一个字节。 1}}。
示例:
dispatch_data_t
输出:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
dispatch_data_t aData = dispatch_data_create("Hello, ", 7, nil, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
dispatch_data_t bData = dispatch_data_create("world!", 6, nil, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
dispatch_data_t cData = dispatch_data_create_concat(aData, bData);
dispatch_data_apply(cData, ^bool(dispatch_data_t _Nonnull region, size_t offset, const void * _Nonnull buffer, size_t size) {
printf("applying at offset %lu, buffer %p, size %lu, contents: [%*.*s]\n", (unsigned long)offset, buffer, (unsigned long)size, (int)size, (int)size, buffer);
return true;
});
}
return 0;
}
好的,这就是applying at offset 0, buffer 0x100407970, size 7, contents: [Hello, ]
applying at offset 7, buffer 0x1004087b0, size 6, contents: [world!]
参数的用途。现在,这与offset
有什么关系?
好吧,dispatch_io_read
两次没有传递相同的字节。一旦它传递了一些字节,就会丢弃它们。下次传递字节时,它们是新读取的新字节。如果你想要旧的字节,你必须自己保持它们。如果您想知道在当前调用回调之前给出了多少旧字节,您必须自己保留该数量。这不是dispatch_io_read
参数的用途。
当offset
调用你时,它可能会传递给你一个dispatch_io_read
,它将其字节存储在多个非连续数组中,所以当你在它上面调用dispatch_data_t
时,你的应用程序多次调用,具有不同的dispatch_data_apply
s和offset
s以及buffer
s。但是这些调用只会让您访问当前调用回调的新字节,而不是之前调用回调的旧字节。