版本:iOS13.5
io.h
索引
-
dispatch_read
通過文件描述符異步讀取數(shù)據(jù) -
dispatch_write
通過文件描述符異步寫入數(shù)據(jù) -
dispatch_io_create
根據(jù)文件描述符創(chuàng)建調(diào)度I / O通道 -
dispatch_io_create_with_path
根據(jù)路徑名創(chuàng)建調(diào)度I / O通道 -
dispatch_io_create_with_io
從現(xiàn)有的調(diào)度I / O通道創(chuàng)建一個新的調(diào)度I / O通道 -
dispatch_io_read
在指定的I / O通道上異步執(zhí)行讀取操作 -
dispatch_io_write
在指定的I / O通道上異步執(zhí)行寫入操作 -
dispatch_io_close
關(guān)閉指定的I / O通道以進行新的讀取或?qū)懭氩僮?/li> -
dispatch_io_barrier
在指定的I / O通道上安排屏障操作 -
dispatch_io_get_descriptor
獲取I / O通道的文件描述符 -
dispatch_io_set_high_water
設(shè)置I / O通道上所有操作的高水位線 -
dispatch_io_set_low_water
設(shè)置I / O通道上所有操作的低水位線 -
dispatch_io_set_interval
設(shè)置一個納秒間隔,所有操作的回調(diào)將按間隔時間排隊。
詳解
- 通過文件描述符異步讀取數(shù)據(jù)
void dispatch_read(dispatch_fd_t fd, size_t length,
dispatch_queue_t queue, void (^handler)(dispatch_data_t data, int error));
當異步讀取操作完成或發(fā)生錯誤時,將handler加入隊列queue再執(zhí)行。
fd 要讀取數(shù)據(jù)的文件描述符 可通過下面代碼創(chuàng)建
//文件位置
NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
#define O_RDONLY 0x0000 //只讀
#define O_WRONLY 0x0001 //只寫
#define O_RDWR 0x0002 //讀寫
#define O_ACCMODE 0x0003 //
length 從文件描述符讀取的數(shù)據(jù)長度 若為SIZE_MAX,表示讀取文件描述符當前可用的所有數(shù)據(jù)。
queue 隊列 通過dispatch_queue_create創(chuàng)建
handler 讀取完成時回調(diào)
data 從文件描述符讀取的數(shù)據(jù)
error 讀取操作的錯誤;如果讀取成功,則為0。
例:
//文件位置
NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
//創(chuàng)建fd
dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
//創(chuàng)建隊列
dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_read(fd, SIZE_MAX, queue, ^(dispatch_data_t _Nonnull data, int error) {
UIImage *image = [UIImage imageWithData:(NSData *)data];
NSLog(@"%f %f", image.size.width, image.size.height);
close(fd);
});
- 通過文件描述符異步寫入數(shù)據(jù)
void dispatch_write(dispatch_fd_t fd, dispatch_data_t data,
dispatch_queue_t queue, void (^handler)(dispatch_data_t _Nullable data, int error));
當異步寫入操作完成或發(fā)生錯誤時,將handler加入隊列queue再執(zhí)行。
data 要寫入文件描述符的數(shù)據(jù)對象
handler 寫入操作完成時回調(diào)
data 無法寫入I / O通道的數(shù)據(jù),寫入成功時為NULL。
error 寫入操作的錯誤;如果寫入成功,則為0。
例:
dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
NSString *path1 = [[NSBundle mainBundle] pathForResource:@"333" ofType:@"jpeg"];
dispatch_fd_t fd1 = open(path1.UTF8String, O_RDWR);
char charbuffer[] = {"1234567890"};
dispatch_data_t data = dispatch_data_create(charbuffer, 10 * sizeof(char), queue, NULL);
dispatch_write(fd1, data, queue, ^(dispatch_data_t _Nullable data, int error) {
NSLog(@"%d", error);
close(fd1);
});
- 根據(jù)文件描述符創(chuàng)建調(diào)度I / O通道
dispatch_io_t dispatch_io_create(dispatch_io_type_t type, dispatch_fd_t fd,
dispatch_queue_t queue, void (^cleanup_handler)(int error));
type io通道類型
//此類型通道的讀取和寫入操作是按順序執(zhí)行的(按創(chuàng)建順序)
//并且在操作開始執(zhí)行時在文件指針位置處讀取/寫入數(shù)據(jù)。
//可以同時執(zhí)行不同類型的操作(讀與寫)。
//傳遞給此類型通道上的操作的偏移量off_t offset將無效
#define DISPATCH_IO_STREAM 0
//可以同時執(zhí)行這種類型的通道上的讀取和寫入操作,并以指定的偏移量off_t offset讀取/寫入數(shù)據(jù)。
//為無法查找的文件描述符創(chuàng)建此類型的通道將導(dǎo)致錯誤。
#define DISPATCH_IO_RANDOM 1
cleanup_handler 當系統(tǒng)放棄對文件描述符的控制權(quán)時要放入隊列queue中的回調(diào)
error 如果由于創(chuàng)建通道失敗使系統(tǒng)放棄控制,則為錯誤,否則為0
例:
NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_io_t io = dispatch_io_create(DISPATCH_IO_RANDOM, fd, queue, ^(int error) {
close(fd);
});
- 根據(jù)路徑名創(chuàng)建調(diào)度I / O通道
dispatch_io_t dispatch_io_create_with_path(dispatch_io_type_t type,
const char *path, int oflag, mode_t mode,
dispatch_queue_t queue, void (^cleanup_handler)(int error));
當通道上的第一個I / O操作準備好執(zhí)行時,指定的路徑,oflag和mode參數(shù)將傳遞給open(2)
path 絕對路徑
oflag 在路徑中打開文件時傳遞給open(2)的標志
mode 在路徑創(chuàng)建文件時傳遞給open(2)的模式,否則為0。
cleanup_handler 系統(tǒng)關(guān)閉路徑下的文件時放入隊列queue的回調(diào)
error 如果創(chuàng)建或打開指定文件的通道失敗使系統(tǒng)放棄控制時,則為錯誤,否則為0
例:
NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_io_t io1 = dispatch_io_create_with_path(DISPATCH_IO_RANDOM, path.UTF8String, 0, 0, queue, ^(int error) {
close(fd);
});
- 從現(xiàn)有的調(diào)度I / O通道創(chuàng)建一個新的調(diào)度I / O通道
dispatch_io_t dispatch_io_create_with_io(dispatch_io_type_t type, dispatch_io_t io,
dispatch_queue_t queue, void (^cleanup_handler)(int error));
新通道繼承與現(xiàn)有通道關(guān)聯(lián)的文件描述符或路徑名,但不繼承其通道類型type或策略
策略為(dispatch_io_set_high_water、dispatch_io_set_low_water、dispatch_io_set_interval)等
io 原io通道
cleanup_handler 當系統(tǒng)放棄對文件描述符的控制(或重新關(guān)閉路徑中的文件)時放入隊列queue的回調(diào)
error 如果由于創(chuàng)建通道失敗使系統(tǒng)放棄控制,則為錯誤,否則為0
例:
NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_io_t io = dispatch_io_create(DISPATCH_IO_RANDOM, fd, queue, ^(int error) {
close(fd);
});
dispatch_io_t io2 = dispatch_io_create_with_io(DISPATCH_IO_RANDOM, io, queue, ^(int error) {
});
- 在指定的I / O通道上異步執(zhí)行讀取操作
void dispatch_io_read(dispatch_io_t channel, off_t offset,size_t length,
dispatch_queue_t queue,dispatch_io_handler_t io_handler);
根據(jù)系統(tǒng)的一般負載和在I / O通道上指定的策略,將io_handler回調(diào)在queue上排隊一次或多次。
channel I / O通道
offset 相對于從其開始讀取的通道位置的偏移量(僅適用于DISPATCH_IO_RANDOM)。
length 從I / O通道讀取的數(shù)據(jù)長度,若為SIZE_MAX,表示全部讀取
io_handler 準備好傳遞數(shù)據(jù)時的回調(diào)
typedef void (^dispatch_io_handler_t)(bool done, dispatch_data_t _Nullable data,
int error);
done 指示操作是否完成
data 從I / O通道讀取的數(shù)據(jù)的對象,或者為NULL
error 讀取操作的錯誤;如果讀取成功,則為0
例:
NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_io_t io = dispatch_io_create(DISPATCH_IO_RANDOM, fd, queue, ^(int error) {
close(fd);
});
dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t _Nullable data, int error) {
if (error == 0) {
size_t len = dispatch_data_get_size(data);
if (len > 0) {
UIImage *image = [UIImage imageWithData:(NSData *)data];
NSLog(@"%f %f", image.size.width, image.size.height);
}
}
if (done) {
NSLog(@"已全部讀取完成");
}
});
輸出:
658.000000 298.000000
已全部讀取完成
- 在指定的I / O通道上異步執(zhí)行寫入操作
void dispatch_io_write(dispatch_io_t channel, off_t offset, dispatch_data_t data,
dispatch_queue_t queue, dispatch_io_handler_t io_handler);
根據(jù)系統(tǒng)的一般負載和在I / O通道上指定的策略,將io_handler回調(diào)在queue上排隊一次或多次。
offset 相對于開始寫入的通道位置偏移(僅適用于DISPATCH_IO_RANDOM )
data 要寫入I / O通道的數(shù)據(jù)。數(shù)據(jù)對象將由系統(tǒng)保留,直到寫入操作完成
io_handler 傳遞數(shù)據(jù)時的回調(diào)
typedef void (^dispatch_io_handler_t)(bool done, dispatch_data_t _Nullable data,
int error);
done 指示操作是否完成
data 被寫入I / O通道的剩余的數(shù)據(jù)對象,若全部寫入則為NULL
error 寫入操作的錯誤;如果寫入成功,則為0
例:
NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_io_t io = dispatch_io_create(DISPATCH_IO_RANDOM, fd, queue, ^(int error) {
close(fd);
});
char charbuffer[] = {"1234567890"};
dispatch_data_t data = dispatch_data_create(charbuffer, 10 * sizeof(char), queue, NULL);
dispatch_io_write(io, 0, data, queue, ^(bool done, dispatch_data_t _Nullable data, int error) {
if (done) {
NSLog(@"已全部寫入完成");
}
});
輸出:
已全部寫入完成
- 關(guān)閉指定的I / O通道以進行新的讀取或?qū)懭氩僮?/li>
void dispatch_io_close(dispatch_io_t channel, dispatch_io_close_flags_t flags);
flags 關(guān)閉操作的標志
#define DISPATCH_IO_STOP 0x1當通道關(guān)閉時,停止對通道的未完成操作
- 在指定的I / O通道上安排屏障操作
void dispatch_io_barrier(dispatch_io_t channel, dispatch_block_t barrier);
barrier回調(diào)會放入通道channel的隊列queue中,通道上的所有先前的調(diào)度操作都會完成。但直到barrier回調(diào)執(zhí)行之前,之后添加的調(diào)度操作都不會開始。
barrier 屏障操作回調(diào)typedef void (^dispatch_block_t)(void);
例:
NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_io_t io = dispatch_io_create(DISPATCH_IO_RANDOM, fd, queue, ^(int error) {
close(fd);
});
dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t _Nullable data, int error) {
if (done) {
NSLog(@"讀取操作1完成");
}
});
dispatch_io_barrier(io, ^{
sleep(10);
});
dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t _Nullable data, int error) {
if (done) {
NSLog(@"讀取操作2完成");
}
});
輸出:操作1完成10秒后操作2才完成
16:20:19.506332+0800 DEMO[67133:7469651] 讀取操作1完成
16:20:29.510332+0800 DEMO[67133:7469652] 讀取操作2完成
- 獲取I / O通道的文件描述符
dispatch_fd_t dispatch_io_get_descriptor(dispatch_io_t channel);
- 設(shè)置I / O通道上所有操作的高水位線
void dispatch_io_set_high_water(dispatch_io_t channel, size_t high_water);
high_water 高水位線的字節(jié)數(shù),默認為SIZE_MAX
- 設(shè)置I / O通道上所有操作的低水位線
void dispatch_io_set_low_water(dispatch_io_t channel, size_t low_water);
I / O管道通常接收大于低水位線的數(shù)據(jù)量。如果需要固定大小的數(shù)據(jù)量,則將低水位標記和高水位標記都設(shè)置為該大小。
low_water 低水位線的字節(jié)數(shù),默認未指定,若要讓操作不執(zhí)行回調(diào),請將此值設(shè)為SIZE_MAX
例:
dispatch_io_set_high_water(io, 10000);
dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t _Nullable data, int error) {
NSLog(@"error=%d data_size =%ld", error, dispatch_data_get_size(data));
});
輸出:總共讀取了5次 每次讀取最大為10000
error=0 data_size =10000
error=0 data_size =10000
error=0 data_size =10000
error=0 data_size =2909
error=0 data_size =0
例:
dispatch_io_set_high_water(io, 9000);
dispatch_io_set_low_water(io, 8000);
dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t _Nullable data, int error) {
NSLog(@"error=%d data_size =%ld", error, dispatch_data_get_size(data));
});
輸出:ps:```dispatch_io_set_low_water```用法不明,有待開發(fā)
error=0 data_size =9000
error=0 data_size =9000
error=0 data_size =9000
error=0 data_size =5909
error=0 data_size =0
- 設(shè)置一個納秒間隔,所有操作的回調(diào)將按間隔時間排隊。
void dispatch_io_set_interval(dispatch_io_t channel,
uint64_t interval, dispatch_io_interval_flags_t flags);
這允許應(yīng)用程序接收有關(guān)讀取和寫入操作進度的定期反饋,例如為了顯示進度條。
interval 各回調(diào)之間的間隔時間(納秒)
flags 數(shù)據(jù)傳遞行為的標志
#define DISPATCH_IO_STRICT_INTERVAL 0x1即使準備好傳遞的數(shù)據(jù)量低于低水位線(或零),也可以按通道的間隔設(shè)置讓回調(diào)排隊。
例:
dispatch_io_set_interval(io, 1 * NSEC_PER_SEC, DISPATCH_IO_STRICT_INTERVAL);
dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t _Nullable data, int error) {
if (done) {
NSLog(@"讀取操作1完成");
}
});
dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t _Nullable data, int error) {
if (done) {
NSLog(@"讀取操作2完成");
}
});
dispatch_io_read(io, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t _Nullable data, int error) {
if (done) {
NSLog(@"讀取操作3完成");
}
});
輸出:并沒有間隔一秒 不知為何
16:58:43.854467+0800 DEMO[67854:7526310] 讀取操作1完成
16:58:43.854501+0800 DEMO[67854:7526297] 讀取操作2完成
16:58:43.854521+0800 DEMO[67854:7526328] 讀取操作3完成
用法
用法1:并行
NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_io_t io = dispatch_io_create(DISPATCH_IO_RANDOM, fd, queue, ^(int error) {
close(fd);
});
long long fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil].fileSize;
NSMutableData *totalData = [[NSMutableData alloc] initWithLength:fileSize];
dispatch_group_t group = dispatch_group_create();
size_t offset = 1024;
for (off_t currentSize = 0; currentSize <= fileSize; currentSize += offset) {
dispatch_group_enter(group);
dispatch_io_read(io, currentSize, offset, queue, ^(bool done, dispatch_data_t _Nullable data, int error) {
if (error == 0) {
size_t len = dispatch_data_get_size(data);
if (len > 0) {
const void *bytes = NULL;
(void)dispatch_data_create_map(data, &bytes, &len);
//當queue為DISPATCH_QUEUE_CONCURRENT并行時 通過replaceBytesInRange來替換數(shù)據(jù)
[totalData replaceBytesInRange:NSMakeRange(currentSize, len) withBytes:bytes];
}
}
if (done) {
dispatch_group_leave(group);
}
});
}
dispatch_group_notify(group, queue, ^{
UIImage *image = [UIImage imageWithData:totalData];
NSLog(@"%f %f", image.size.width, image.size.height);
});
用法2:串行
NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_SERIAL);
dispatch_io_t io = dispatch_io_create(DISPATCH_IO_RANDOM, fd, queue, ^(int error) {
close(fd);
});
long long fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil].fileSize;
NSMutableData *totalData = [[NSMutableData alloc] init];
dispatch_group_t group = dispatch_group_create();
size_t offset = 1024;
for (off_t currentSize = 0; currentSize <= fileSize; currentSize += offset) {
dispatch_group_enter(group);
dispatch_io_read(io, currentSize, offset, queue, ^(bool done, dispatch_data_t _Nullable data, int error) {
if (error == 0) {
size_t len = dispatch_data_get_size(data);
if (len > 0) {
//當queue為DISPATCH_QUEUE_SERIAL串行時 通過appendData直接合并數(shù)據(jù)
[totalData appendData:(NSData *)data];
}
}
if (done) {
dispatch_group_leave(group);
}
});
}
dispatch_group_notify(group, queue, ^{
UIImage *image = [UIImage imageWithData:totalData];
NSLog(@"%f %f", image.size.width, image.size.height);
});
用法3:io類型為DISPATCH_IO_STREAM
NSString *path = [[NSBundle mainBundle] pathForResource:@"222" ofType:@"jpeg"];
dispatch_fd_t fd = open(path.UTF8String, O_RDWR);
dispatch_queue_t queue = dispatch_queue_create("io_queue", DISPATCH_QUEUE_SERIAL);
dispatch_io_t io = dispatch_io_create(DISPATCH_IO_STREAM, fd, queue, ^(int error) {
close(fd);
});
long long fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil].fileSize;
NSMutableData *totalData = [[NSMutableData alloc] init];
dispatch_group_t group = dispatch_group_create();
size_t offset = 1024;
for (off_t currentSize = 0; currentSize <= fileSize; currentSize += offset) {
dispatch_group_enter(group);
//io類型為DISPATCH_IO_STREAM時 不用設(shè)置off_t offset屬性
dispatch_io_read(io, 0, offset, queue, ^(bool done, dispatch_data_t _Nullable data, int error) {
if (error == 0) {
size_t len = dispatch_data_get_size(data);
if (len > 0) {
[totalData appendData:(NSData *)data];
}
}
if (done) {
dispatch_group_leave(group);
}
});
}
dispatch_group_notify(group, queue, ^{
UIImage *image = [UIImage imageWithData:totalData];
NSLog(@"%f %f", image.size.width, image.size.height);
});