【问题标题】:feof() in C file handlingC 文件处理中的 feof()
【发布时间】:2010-04-13 23:20:35
【问题描述】:

我正在逐字节读取二进制文件,我需要确定是否达到了 eof。

feof() 不起作用,因为“仅在对不存在的字节进行读取请求时才设置 eof”。所以,我可以有我的自定义 check_eof 喜欢:

if ( fread(&byte,sizeof(byte),1,fp) != 1) {
    if(feof(fp))
    return true;
}
return false;

但问题是,如果没有达到 eof,我的文件指针会向前移动一个字节。 所以一个解决方案可能是使用ftell() 然后fseek() 让它到正确的位置。

另一种解决方案可能是将字节提前缓冲在一些临时存储中。

有更好的解决方案吗?

【问题讨论】:

  • 您需要将流 (fp) 传递给feof

标签: c file-handling feof


【解决方案1】:

如果您一次读取一个字节,惯用的方法是使用fgetc

int c;
while ((c = fgetc(fp)) != EOF) {
   // Do something.
}

然后你就不需要处理feof了。

【讨论】:

  • 你仍然需要处理 feof(或 ferror)。当循环终止时,您需要检查它是否因为到达文件末尾而终止,或者是否存在读取错误。做到这一点的唯一方法是使用其中一个功能。 (除非您不关心报告错误。)
【解决方案2】:

我通常会这样做:

int get_next_char(FILE* fp, char *ch)
{
    return fread(ch, sizeof(char),1, fp) == 1;
}

// main loop
char ch;
while (get_next_char(fp, &ch))
    process_char(ch);

if (!feof(fp))
    handle_unexpected_input_error(fp);

【讨论】:

  • 我认为这是最好的建议 - 重构您调用的代码,这样它就不需要在尝试读取之前检查 eof(这实际上意味着我想提前缓冲一个字符)。
【解决方案3】:

最好对代码进行结构化,以便尝试读取一些数据,如果由于到达文件末尾而导致读取不成功,则在此处处理(即参见Kristopher Johnson's answer)。

如果你非常讨厌这个,你可以使用ungetc 将单个字符返回到流中,它将在下一次读取调用中可用:

int c = fgetc(fp);
if (c == EOF)
{
    // handle eof / error
}
else
{
    ungetc(c, fp);

    // the next read call is guaranteed to return at least one byte

}

【讨论】:

    【解决方案4】:

    我不清楚,但是如果您有兴趣在读取字节之前知道是否已达到 EOF,请将您的 feof() 测试放在 fread() 之前而不是之后。
    实际上,如果我没看错,你甚至不想这样做:

    return feof(fp) ? true : false;
    

    【讨论】:

    • feof 不是这样工作的。仅仅在文件的末尾是不够的;您必须在feof 返回true 之前尝试过去读取文件末尾。
    • 正确。这不会使我的答案错误,只是无关紧要(OP 应该已经在读取过去的 eof 时收到错误)
    【解决方案5】:

    我建议使用:

    fseek(myFile, 0, SEEK_END);
    fileLen = ftell(myFile);
    fseek(myfile, 0, SEEK_SET);
    

    当你第一次打开文件时确定长度。然后将您的读取循环设置为从不读取结尾。您可以使用ftell 确定您的位置,并与 fileLen 进行比较以确定您还需要走多远。

    【讨论】:

    • 总是假设文件在读取时会改变大小 - 更大或更小。
    猜你喜欢
    • 2012-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-09
    • 2021-06-04
    • 2011-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多