Dispatch Source Reader - Как определить конец файла? - PullRequest
3 голосов
/ 11 апреля 2011

Вдохновленный документацией Apple , я экспериментирую с использованием источника диспетчеризации 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 Ответ

1 голос
/ 06 мая 2011

AFAIK, вы должны сравнить прочитанные байты с длиной файла.

Кроме того, источник отправки GCD использует kqueue с EVFILT_READ, поэтому он не очень полезен для обычных файлов. Я рекомендую вам использовать открыть / lseek / прочитать / закрыть файл в глобальной очереди.

  • Re: kqueue и EVFILT_READ для файлов

    По большей части фильтры чтения на самом деле бесполезны для обычных файлов, поскольку - хорошо - они всегда читаемы, если в них остаются данные, и они дают четкое условие EOF. Вы не можете действительно обрабатывать файлы, как если бы они были конвейерами - то есть не ожидайте, что fle, у которого fp равен EOF, затем расширяется, поэтому в файле появляется больше данных, что приводит к выполнению EVFILT_READ. Это будет работать в случае не EV_POLL для обычных файлов, но не будет работать для специальных файлов.

    Аналогично, по крайней мере, для большинства обычных блочных устройств (дисков и т. Д.) Они также всегда читаются, пока вы не дойдете до конца устройства, и там тоже есть четкая индикация EOF, поэтому они там не слишком полезны. либо (не похоже, что на диск, созданный в 1998 году, внезапно появятся новые дисковые блоки).

...