fgets正在从已关闭的文件描述符中读取更多数据

时间:2011-09-07 17:29:18

标签: c linux file-io eof fgets

我在linux上面临fgets()的一些问题。 fgets从关闭的文件描述符返回数据。 如果文件关闭,我希望它返回EOF。 我能够提出我的问题的简化版本。

int main()
{
        int i=0, j;
        FILE *FD;
        char p[128];
        FD = fopen("junk", "r");
        while(fgets(p, sizeof(p), FD))
        {  
                close(fileno(FD));
                printf("lineno=%d\n", i++);
        }  
        return 0;
}

我希望它只打印一行。 这个问题有解决办法吗?

更新: 正如有人在下面回答的那样,fgets正在缓冲文件 甚至在FD关闭后返回数据。 它正在缓冲4kB的数据。如果文件大小超过4k, 读取4KB后,它会获得EOF,打印停止。否则,如果 文件大小谢谢4k,它打印到文件末尾。

3 个答案:

答案 0 :(得分:5)

在已关闭的文件上调用fgets()具有未定义的行为。换句话说,不保证返回EOF。

答案 1 :(得分:1)

像其他人所说,close(fileno(FD));是一个坏主意。如果这样做,相同的文件描述符可能会被重用于另一个文件,而fgets会突然读取该fd。对于多线程应用程序尤其如此。

此外,fgets已缓冲。它可能在第一次调用时从文件中读取了大量数据,然后调用只返回缓冲区中的更多数据。

相反,做这样的事情:

int main(void)
{
        int i=0, j;
        FILE *FD;
        char p[128];
        FD = fopen("junk", "r");
        while(FD && fgets(p, sizeof(p), FD))
        {  
                fclose(FD);
                FD = NULL;
                printf("lineno=%d\n", i++);
        }  
        return 0;
}

答案 2 :(得分:0)

关闭后使用文件描述符可能会导致不可预测/未定义的行为。你可能应该避免这样做。

发布的示例中可能发生的是打开并读取流。读取数据可能会将更多数据放入基础流中。因此,即使基础文件描述符已关闭,流的句柄仍将包含更多要读取的数据。同样,这可能是不可预测的。