dispatch io.h

版本:iOS13.5

io.h

dispatch其他文件通道

索引

  • 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_waterdispatch_io_set_low_waterdispatch_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);
    });
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容