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