3

Appleのドキュメントに触発されて、私は従来NSInputStreamの実行ループベースのアプローチを使用する代わりに、GCDディスパッチソースを使用してファイルから非同期的に読み取ることを実験しています。

ただし、ファイルの読み取りが完了したことを検出する方法がわかりません。を使用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);
4

1 に答える 1

2

私の知る限り、読み取りバイト数とファイルの長さを比較する必要があります。

また、GCD ディスパッチ ソースは EVFILT_READ で kqueue を使用するため、通常のファイルにはあま​​り役に立ちません。Global Queue 内のファイルを open/lseek/read/close を使用することをお勧めします。

  • Re: ファイルの kqueue と EVFILT_READ

    ほとんどの場合、読み取りフィルターは通常のファイルにはあま​​り役に立ちません。データが残っている限り、読み取りフィルターは常に読み取り可能であり、明確な EOF 条件を与えるためです。ファイルをパイプのように実際に扱うことはできません。つまり、fp が EOF にあるファイルが拡張されて、ファイル内により多くのデータが存在し、EVFILT_READ が true になることを期待しないでください。これは、EV_POLL 以外の場合、通常のファイルでは機能しますが、特殊なファイルでは機能しません。

    同様に、少なくともほとんどの通常のブロック デバイス (ディスクなど) では、デバイスの最後に到達するまで常に読み取り可能であり、そこにも明確な EOF 表示があるため、そこでもあまり役に立ちません (たとえば、1998 年に製造された大皿に、より多くのディスク ブロックが突然到着するわけではありません)。

于 2011-05-06T07:53:09.930 に答える