【问题标题】:Using fseek with a file pointer that points to stdin将 fseek 与指向标准输入的文件指针一起使用
【发布时间】:2011-06-22 12:19:53
【问题描述】:

根据命令行参数,我将文件指针设置为指向指定文件或标准输入(用于管道)。然后我将此指针传递给许多不同的函数以从文件中读取。下面是获取文件指针的函数:

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);
}

【问题讨论】:

  • 您的示例代码对我来说看起来不错。 (除非文件不存在,但这与您的问题无关)
  • 对我来说似乎是正确的。它是什么编译器?您可以尝试在 bar() 函数中打印两个指针(stdin 和 myFile)以检查它们是否相同。
  • @leonbloy:我发现问题实际上出在fseek()。显然当指针指向标准输入时它不起作用?对此有什么想法吗? (更新问题)

标签: c file pointers stdin piping


【解决方案1】:

是的,fseek 不能在 stdin 上工作是完全正常的——它通常只能在磁盘文件或类似的东西上工作。

虽然它确实是一个 POSIX 的东西,但您通常可以使用 if (isatty(fileno(myFile))) 至少很好地了解搜索是否可以在特定文件中工作。在某些情况下,isatty 和/或fileno 将有一个前导下划线(例如,微软编译器提供的版本的 IIRC)。

【讨论】:

  • 那么我想我的问题是——这可能很愚蠢——我将如何移动到流中的不同索引?我认为会有比在循环 n 次中调用 fgetc(myFile) 更优雅的解决方案?
  • @Tyler Treat:没有——这是流和文件之间的根本区别。从概念上讲,来自流的输入不会存储在任何地方 - 流是短暂的,在您使用它时生成。如果您需要在流中的数据中四处寻找,您应该将其读入内存并在那里寻找(或者,如果它特别大,将其读入临时文件)。
  • 我在 C11 规范中找不到关于“fseek 在标准输入上不起作用是完全正常的”的支持。当stdin 是文本流时,你有 C 规范支持吗?
  • 将错误的“fseek 不能在标准输入上工作”更改为“fseek 不能在管道、套接字或 FIFO 上工作”。这是一个示例,其中fseekstdin 上运行良好,因为stdin 来自(可搜索的)文件:./a.out <a.out
  • @IanD.Allen:你已经断章取义了。我实际上说的一点也不对,任何具有 10 岁儿童阅读能力的人都会知道其中的区别。
【解决方案2】:

Fseek() 基于 lseek(),lseek 手册页讨论了可能的错误,包括:

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

如果stdin连接到一个伪tty,我相信它会有socket行为。

【讨论】:

  • ANSI C 对此有什么说法吗?
【解决方案3】:

这是 ANSI 标准中关于 fseek 函数的相关条目:

对于文本流,偏移量应为零,或偏移量应为先前成功调用与同一文件关联的流上的 ftell 函数返回的值,并且应为 SEEK_SET

所以,可能,但有一些限制

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 2022-11-11
    • 2017-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多