Использование fseek с указателем файла, который указывает на стандартный ввод - PullRequest
10 голосов
/ 07 февраля 2011

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

FILE *getFile(int argc, char *argv[]) {
    FILE *myFile = NULL;
    if (argc == 2) {
        myFile = fopen(argv[1], "r");
        if (myFile == NULL)
           fprintf(stderr, "File \"%s\" not found\n", argv[1]);
    }
    else
        myFile = stdin;
    return myFile;
}

Когда он указывает на стандартный ввод, fseek, похоже, не работает.Под этим я подразумеваю, что я использую его, а затем использую fgetc, и я получаю неожиданные результаты.Является ли это ожидаемым поведением, и если да, то как мне перейти в другие места в потоке?

Например:

int main(int argc, char *argv[]) {
    FILE *myFile = getFile(argc, argv); // assume pointer is set to stdin
    int x = fgetc(myFile); // expected result
    int y = fgetc(myFile); // expected result
    int z = fgetc(myFile); // expected result

    int foo = bar(myFile); // unexpected result

    return 0;
}

int bar(FILE *myFile) {
    fseek(myFile, 4, 0);
    return fgetc(myFile);
}

Ответы [ 3 ]

13 голосов
/ 07 февраля 2011

Да, совершенно нормально, что fseek не будет работать на stdin - обычно оно будет работать только с файлом на диске или чем-то похожим.

Хотя это действительно POSIX, вы обычно можете использовать if (isatty(fileno(myFile))), чтобы получить хотя бы довольно хорошее представление о том, будет ли поиск работать в определенном файле. В некоторых случаях isatty и / или fileno будут иметь начальное подчеркивание (например, IIRC версии, предоставляемые компиляторами Microsoft).

2 голосов
/ 07 февраля 2011

Fseek () основан на lseek (), а на справочной странице lseek рассматриваются возможные ошибки, в том числе:

 [ESPIPE]           Fildes is associated with a pipe, socket, or FIFO.

Если stdin подключен к псевдотерминалу, я думаю, что он будет работать с сокетом.

0 голосов
/ 01 апреля 2019

Вот соответствующая запись в стандарте ANSI относительно функции fseek:

Для текстового потока либо смещение должно быть равно нулю, либо смещение должно быть значением, возвращенным ранее успешнымвызов функции ftell для потока, связанного с тем же файлом, и откуда должен быть SEEK_SET

Так что возможно, но с некоторыми ограничениями

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