2011-04-11 80 views
3

Apple's documentation的啓發,我正在嘗試使用GCD調度源從文件異步讀取,而不是使用傳統的NSInputStream和基於運行循環的方法。調度源讀取器 - 如何檢測文件結束?

但是,我不知道如何檢測完成讀取文件。用NSInputStream,你的代表得到一個NSStreamEventEndEncountered事件。對於調度源,我認爲事件處理程序將在文件結束時被調用,但似乎並非如此。我錯過了什麼?

這裏是我的代碼:

const char* fileName = "/Users/Nick/Music/iTunes/iTunes Music Library.xml"; 
int fd = open(fileName, O_NONBLOCK|O_RDONLY); 
assert(fd>0); 

dispatch_source_t readerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, dispatch_get_main_queue()); 

dispatch_source_set_event_handler(readerSource, ^{ 
    char buffer[1024]; 
    size_t estimatedLength = dispatch_source_get_data(readerSource); 

    ssize_t bytesRead = read(fd, buffer, MIN(1024, estimatedLength)); 
    if (bytesRead < 0) { 
     if (errno != EAGAIN) { 
      printf("Unexpected error!"); 
      abort(); 
     } 
    } else if (bytesRead > 0) { 
     printf("Got %ld bytes of data.\n", bytesRead); 
    } else { 
     // bytesRead == 0 
     printf("EOF encountered!\n"); 
     dispatch_source_cancel(readerSource); 
    } 
}); 

dispatch_source_set_cancel_handler(readerSource, ^{ 
    printf("Cancel handler was called.\n"); 
    close(fd); 
    dispatch_release(readerSource); 
}); 

dispatch_resume(readerSource); 

回答

1

據我所知,你要比較與該文件的長度讀取的字節。

此外,GCD調度源使用kqueue和EVFILT_READ,因此它對於常規文件並不是很有用。我建議您在Global Queue中使用open/lseek/read /關閉文件。

  • Re: kqueue and EVFILT_READ on files

    在大多數情況下,讀過濾器是不正規的文件非常有用,因爲 - 好 - 他們總是可讀的,只要他們留在他們的數據,他們會給出明確的EOF狀態。你不能真正把文件看作是管道 - 也就是說,不要指望fp在EOF的文件系統被擴展,所以文件中有更多數據導致EVFILT_READ成爲現實。這將在非EV_POLL的情況下適用於普通文件,但它不適用於特殊文件。同樣,至少對於大多數普通的塊設備(磁盤等)來說,它們總是可讀的,直到你碰到設備的末端,並且在那裏也有一個明確的EOF指示,所以它們並不是很有用在那裏,或者(例如,不像更多的磁盤塊會突然到達1998年建成的磁盤)。

+0

謝謝你,我不知道的「普通文件」的區別。 – 2011-05-10 11:18:03