【问题标题】:Why is fread reaching the EOF early?为什么 fread 提前到达 EOF?
【发布时间】:2010-09-14 21:46:58
【问题描述】:

我正在编写一个将文件读入内存的 C 库。它跳过文件(标题)的前 54 个字节,然后将其余部分作为数据读取。我用fseek判断文件的长度,然后用fread读入文件。

循环运行一次然后结束,因为到达 EOF(没有错误)。最后,bytesRead = 10624,ftell(stream) = 28726,缓冲区包含 28726 个值。我希望 fread 在到达 EOF 时读取 30,000 个字节,文件位置为 30054。

C 不是我的母语,所以我怀疑我在某个地方犯了一个愚蠢的初学者错误。

代码如下:

const size_t headerLen = 54;

FILE * stream;
errno_t ferrno = fopen_s( &stream, filename.c_str(), "r" );
if(ferrno!=0) {
  return -1;
}

fseek( stream, 0L, SEEK_END );
size_t bytesTotal = (size_t)(ftell( stream )) - headerLen; //number of data bytes to read
size_t bytesRead = 0;
BYTE* localBuffer = new BYTE[bytesTotal];
fseek(stream,headerLen,SEEK_SET);
while(!feof(stream) && !ferror(stream)) {
    size_t result = fread(localBuffer+bytesRead,sizeof(BYTE),bytesTotal-bytesRead,stream);
    bytesRead+=result;
}

根据您使用的参考,很明显在模式标志中添加“b”就是答案。为白痴徽章寻求提名。 :-)

This reference 在第二段第二句中谈到它(虽然不在他们的表格中)。

MSDN 直到页面的一半才讨论二进制标志。

OpenGroup 提到了“b”标签的存在,但表示它“没有任何作用”。

【问题讨论】:

  • 我添加了 microsoft 标签,因为 fopen_s 仅在 MS 的 C RTL 中。
  • OpenGroup 确实提到了它:r 或 rb - 打开文件以供阅读。 ...字符“b”没有任何作用,但允许符合 ISO C 标准。请修正您的编辑。
  • 找到文件大小,分配内存后,应该可以一口气读完整个文件了。

标签: c++ c file-io stdio feof


【解决方案1】:

也许这是一个二进制模式问题。尝试以"r+b" 为模式打开文件。

编辑:如评论中所述,"rb" 可能更符合您的原始意图,因为"r+b" 将打开它以进行读/写,而"rb" 是只读的。

【讨论】:

  • 我同意 Evan 的观点,即这可能是二进制模式问题。但是,我很确定 C 标准不保证 ftell 在您使用它时会返回文件的实际长度。我似乎记得它需要返回一个“令牌”,如果你将它传递给 fseek,它将让你回到文件中的相同位置。
  • +1 为 Mike F 和我自己。 Windows 总是用 +b 咬我。
  • 我建议先尝试“rb”,因为“r+b”打开文件文件进行读写,如果你不打算写入文件,你应该继续打开它只读。
  • 我也有同样的想法......根据这个参考,它是实际位置:opengroup.org/onlinepubs/009695399/functions/ftell.html
  • 这就是答案。 “rb”有效。 RTFM 的另一个例子。第一段也这么说:cplusplus.com/reference/clibrary/cstdio/fopen.html
【解决方案2】:

另外值得注意的是,只需将 binmode.obj 包含在您的链接命令中,即可为您打开所有文件。

【讨论】:

    【解决方案3】:

    一个解决方案,基于之前的答案:

        size_t bytesRead = 0;
        BYTE* localBuffer = new BYTE[bytesTotal];
        fseek(stream,headerLen,SEEK_SET);
            while(!feof(stream) && !ferror(stream)) {
            size_t result = fread(localBuffer+bytesRead,sizeof(BYTE),bytesTotal-
            bytesRead,stream);
        bytesRead+=result;
    }
    

    【讨论】:

      猜你喜欢
      • 2017-10-21
      • 1970-01-01
      • 2016-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-11
      • 1970-01-01
      相关资源
      最近更新 更多