Только для чтения буферизованная дата из объекта FILE - PullRequest
1 голос
/ 29 мая 2011

Я хотел бы прочитать только то, что уже находится в буфере объекта FILE, чтобы впоследствии буфер был пуст (и я могу использовать такие вещи, как sendfile, который работает с файловыми дескрипторами). Я придумал эту функцию, которая, кажется, работает на моей 64-битной установке Linux:

int readbuf(FILE *stream, char buf[], size_t *size) {
    off_t pos = ftello(stream);
    if (pos < 0) return -1;
    off_t realpos = lseek(fileno(stream), 0, SEEK_CUR);
    if (realpos < 0) return -1;
    if (pos > realpos) {
        errno = EIO;
        return -1;
    }
    size_t bufsize = realpos - pos;
    if (bufsize > *size) {
        *size = bufsize;
        errno = ERANGE;
        return -1;
    }
    *size = bufsize;
    if (fread(buf, bufsize, 1, stream) < 1) {
        return -1;
    }
    return 0;
}

Теперь мне интересно, могу ли я предположить, что это работает на других POSIX-совместимых операционных системах? (В системах, которые обеспечивают все задействованные функции.)

Ответы [ 3 ]

2 голосов
/ 30 мая 2011

Если базовый файловый дескриптор является доступным для поиска (обычный файл или блочное устройство, если в вашей системе нет других странных объектов для поиска ...), то нет смысла в том, что вы пытаетесь сделать.Просто используйте ftello, чтобы получить логическую позицию в FILE, затем отбросьте FILE и используйте sendfile.Использование уже буферизованных данных в пользовательском пространстве на самом деле медленнее, чем sendfile.

Если базовый дескриптор файла не доступен для поиска, весь ваш подход не работает, потому что lseek всегда будет возвращать -1 и ftello вернет EOF.Возможное решение в этом случае:

  • Используйте dup, чтобы создать новый дескриптор файла со ссылкой на то же описание открытого файла.
  • Открыть /dev/null только для записи и dup2 он поверх старого номера файлового дескриптора, используемого FILE.
  • Чтение из FILE будет успешным до тех пор, пока не будет исчерпан буфер, а затем выдаст ошибки чтения, поскольку дескриптор файла теперь ссылаетсянечитаемый файл.
  • Теперь вы можете читать напрямую с дублированного файла, созданного на первом шаге.Вы также можете свободно fclose FILE.
1 голос
/ 30 мая 2011

Для поиска файлов на платформах Unix вы должны иметь возможность использовать fflush () для координации использования на основе fd с использованием на основе FILE *, в том числе для чтения.Полная информация дана в http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_05_01 и http://pubs.opengroup.org/onlinepubs/9699919799/functions/fflush.html.

Это расширение того, что дает вам стандарт C (что неудивительно).

0 голосов
/ 29 мая 2011

Я не верю, что stdio API гарантирует, что это будет работать на любой системе.Например, он может выполнить readahead, если заметит, что буфер пуст.

Ваше "решение" будет не более чем конкретным хаком реализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...