使用带有指向stdin的文件指针的fseek

Tyl*_*eat 10 c stdin pointers file piping

根据命令行参数,我设置一个文件指针指向指定文件或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;
}
Run Code Online (Sandbox Code Playgroud)

当它指向stdin时,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);
}
Run Code Online (Sandbox Code Playgroud)

Jer*_*fin 13

是的,这是完全正常的,fseek无法正常工作stdin- 它通常只能在磁盘文件或类似的东西上工作.

虽然它确实是一个POSIX的东西,但你通常可以if (isatty(fileno(myFile)))用来至少很好地了解搜索是否适用于特定文件.在某些情况下,isatty和/或fileno将具有前导下划线(例如,IIRC与Microsoft的编译器一起提供的版本).

  • @Tyler Treat:没有 - 这是流和文件之间的根本区别.从概念上讲,流的输入不会存储在任何地方 - 流是短暂的,在您使用它时生成.如果您需要在流中搜索数据,则应将其读入内存并在那里寻找(或者,如果它特别大,则将其读入临时文件中). (4认同)
  • 将错误的“fseek 不适用于 stdin”更改为“fseek 不适用于管道、套接字或 FIFO”。这是一个示例,其中“fseek”在“stdin”上运行得很好,因为“stdin”来自(可查找的)文件:“./a.out <a.out” (3认同)
  • 我在 C11 规范中没有找到关于“fseek 无法在 stdin 上工作是完全正常的”的支持。当“stdin”是文本流时,您是否有 C 规范来支持这一点? (2认同)