最近在研究GCD,網(wǎng)上看了好多博客大部分都是關(guān)于異步,同步線程的問題,在無意中翻閱文檔的時候看到dispatch_io_t這個東西.發(fā)現(xiàn)GCD也可以用來對數(shù)據(jù)進行讀取(Read/Write)操作,作為一名程序猿這無疑激起了我的好奇心,于是我決定帶上火眼金睛看看這是個什么鬼.
.............好吧 我看了看發(fā)現(xiàn)全是英文((⊙o⊙)…,這不是廢話么).既然是廢話,那咱們直接上干貨(求各位看官贖罪,我也只是剛剛了解到基本的用法)
首先dispatch讀取數(shù)據(jù)是屬于 數(shù)據(jù)持久化的一種方式,相對于我們平常用的wirteToFile和其他的方式,dispatc可以分次讀取,可以設(shè)定low_Water或者high_Water,也就是每次讀取的下限和上限,我們利用這一點可以監(jiān)控整個讀取過程的progress,哈哈 是不是很爽.好吧,在讀取之前,我們首先要準備一條路徑,這個沒有什么特別的就是咱們平常用的path
NSString *path = [NSString stringWithFormat:@"%@/Documents/myData.text",NSHomeDirectory()];23NSLog(@"%@",path);
打印出來有助于檢查文件是不是被寫進去了,但是這里我發(fā)現(xiàn)了一個問題,不過不影響讀取,稍后我在拋出這個問題
GCD的讀寫需要我們事先獲取文件打開的權(quán)限和一個文件的描述符,也就是下面這個東西
dispatch_fd_t fd = open(strcpy(myChar, (char*)[path UTF8String]), O_RDWR | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO);
我來解釋一下這個鬼的幾個參數(shù),第一個使我們路徑轉(zhuǎn)成的char類型,沒辦法,純C的東西.后面的是可變長度參數(shù)類型,這里填寫的是我們獲取的權(quán)限,我在網(wǎng)上找了一些后面參數(shù)的解釋
/*O_RDONLY 以只讀方式打開文件
O_WRONLY 以只寫方式打開文件
O_RDWR 以可讀寫方式打開文件. 上述三種旗標(biāo)是互斥的, 也就是不可同時使用, 但可與下列的旗標(biāo)利用OR(|)運算符組合.
O_CREAT 若欲打開的文件不存在則自動建立該文件.
O_EXCL 如果O_CREAT 也被設(shè)置, 此指令會去檢查文件是否存在. 文件若不存在則建立該文件, 否則將導(dǎo)致打開文件錯誤. 此外, 若O_CREAT 與O_EXCL 同時設(shè)置, 并且欲打開的文件為符號連接, 則會打開文件失敗.
O_NOCTTY 如果欲打開的文件為終端機設(shè)備時, 則不會將該終端機當(dāng)成進程控制終端機.
O_TRUNC 若文件存在并且以可寫的方式打開時, 此旗標(biāo)會令文件長度清為0, 而原來存于該文件的資料也會消失.
O_APPEND 當(dāng)讀寫文件時會從文件尾開始移動, 也就是所寫入的數(shù)據(jù)會以附加的方式加入到文件后面.
O_NONBLOCK 以不可阻斷的方式打開文件, 也就是無論有無數(shù)據(jù)讀取或等待, 都會立即返回進程之中.
O_NDELAY 同O_NONBLOCK.
O_SYNC 以同步的方式打開文件.
O_NOFOLLOW 如果參數(shù)pathname 所指的文件為一符號連接, 則會令打開文件失敗.
O_DIRECTORY 如果參數(shù)pathname 所指的文件并非為一目錄, 則會令打開文件失敗躯保。注:此為Linux2. 2 以后特有的旗標(biāo), 以避免一些系統(tǒng)安全問題.
*/
/*S_IRWXU00700 權(quán)限, 代表該文件所有者具有可讀衣屏、可寫及可執(zhí)行的權(quán)限.
S_IRUSR 或S_IREAD, 00400 權(quán)限, 代表該文件所有者具有可讀取的權(quán)限.
S_IWUSR 或S_IWRITE, 00200 權(quán)限, 代表該文件所有者具有可寫入的權(quán)限.
S_IXUSR 或S_IEXEC, 00100 權(quán)限, 代表該文件所有者具有可執(zhí)行的權(quán)限.
S_IRWXG 00070 權(quán)限, 代表該文件用戶組具有可讀异袄、可寫及可執(zhí)行的權(quán)限.
S_IRGRP 00040 權(quán)限, 代表該文件用戶組具有可讀的權(quán)限.
S_IWGRP 00020 權(quán)限, 代表該文件用戶組具有可寫入的權(quán)限.
S_IXGRP 00010 權(quán)限, 代表該文件用戶組具有可執(zhí)行的權(quán)限.
S_IRWXO 00007 權(quán)限, 代表其他用戶具有可讀吨瞎、可寫及可執(zhí)行的權(quán)限.
S_IROTH 00004 權(quán)限, 代表其他用戶具有可讀的權(quán)限
S_IWOTH 00002 權(quán)限, 代表其他用戶具有可寫入的權(quán)限.
S_IXOTH 00001 權(quán)限, 代表其他用戶具有可執(zhí)行的權(quán)限.*/
接下來,我們要給gcd準備一條線程,創(chuàng)建線程有好多種方式,這里我們使用帶有標(biāo)志的,便于以后線程出問題調(diào)試,嘿嘿
dispatch_queue_t myQueue = dispatch_queue_create("myOnlyQueue", DISPATCH_QUEUE_CONCURRENT);
搞定這些之后我們需要給gcd搞一個通道channle,創(chuàng)建通道的方式也是有好幾種,我先給大家介紹一下創(chuàng)建通道的幾個參數(shù)吧
dispatch_io_create_with_path(dispatch_io_type_t type,constchar*path,intoflag, mode_t mode,
dispatch_queue_t queue,void(^cleanup_handler)(interror));
第一個是通道本身的type,只有兩種,一個是 ?0 ?這種方式會忽略我們下面要創(chuàng)建的offset參數(shù)
DISPATCH_IO_STREAM
另外一個是 ? ?1 ?需要我們創(chuàng)建一個offset參數(shù)用來找到file的descriptor
DISPATCH_IO_RANDOM
第二個參數(shù)是路徑,第三個是旗標(biāo),搞過Linux的應(yīng)該是知道的,這里我們用O_RDWR,第四個是如果放棄操作或者打開指定文件失敗的錯誤碼,一般寫0,第四個就是我們上面創(chuàng)建的queue,最后的是我們創(chuàng)建通道時的錯誤碼
dispatch_io_t dispatchio = dispatch_io_create_with_path(DISPATCH_IO_STREAM, path.UTF8String, O_RDWR,0, myQueue, ^(interror) {
close(fd);
});
上面只是創(chuàng)建通道的一種方式,如果我記得不錯的話應(yīng)該是一共有4種,其他的各位看官們可以自己試試
首先我們來搞一個簡單的東西寫入文件
constchardaxiao[] ="Hello? World !";
off_t offt =sizeof(daxiao);
size_t size=sizeof(daxiao);
然后我們開始把上面這句話搞到gcd的data里面去
dispatch_data_t datas = dispatch_data_create(daxiao, size, myQueue, NULL);
最后開始我們的寫入操作
dispatch_io_write(dispatchio,0, datas, myQueue, ^(booldone, dispatch_data_t data,interror) {
});
這樣我們就可以把Hello ?World !寫入文件了,從路徑打開文件查看,的確寫入了,但是不知道為何后面會多出許多沒用的東西來,這個也是我最一開始提到的問題,目前我還沒有鬧明白,如果哪位大神知道是咋回事,還請告知小弟,不勝感激!!!
不過多出來的東西不影響我們讀取數(shù)據(jù)
下面我們開始讀取已經(jīng)寫好的文件
很簡單
dispatch_io_set_high_water(dispatchio,1);
dispatch_io_read(dispatchio,0,10, myQueue, ^(booldone, dispatch_data_t data,interror) {
NSString*string= [[NSString alloc] initWithData:(NSData *)data encoding:NSUTF8StringEncoding];if(done) {
NSLog(@"%@",string);
}else{
NSLog(@"我的大刀早已饑渴難耐了!");
}
第一行就是我說的設(shè)定最高讀取上限,后面那個1 是最高讀取1字節(jié),所以如果你運行成功后會發(fā)現(xiàn) dispatch_io_read后面的回調(diào)block會走好幾遍,也就是說
NSLog(@"我的大刀早已饑渴難耐了!");
這個會打印好多次,利用這一點我們可以監(jiān)控讀取文件的進度,這種方式就是利用線程多次讀取文件,相比普通的方式可以提高速度.
好吧,我文筆有限,后面我會繼續(xù)講解GCD數(shù)據(jù)持久化的另外一種方式,不過大同小異,有興趣的看官可以繼續(xù)到我這里來看看.
最后:由于我也是剛剛了解這個東西,再加上本人英語渣渣,難免會有錯誤的敵方,歡迎各位大神不吝賜教,指出錯誤,小弟在此拜謝!