Средство чтения исходного кода отправки — Как определить конец файла?

#c #cocoa #file-io #grand-central-dispatch

#c #cocoa #file-io #grand-central-dispatch

Вопрос:

Вдохновленный документацией 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:

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

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

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

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

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

Комментарии:

1. Спасибо за это, я не знал о различии между «обычным файлом».