为什么fread会提早到达EOF?

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

循环运行一次然后结束,因为达到了EOF(没有错误)。 最后,bytesRead = 10624,ftell(stream)= 28726,缓冲区包含28726个值。 我希望fread读取30,000字节,当达到EOF时文件位置为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”就是答案。 寻求骷髅徽章的提名。 🙂

该引用在第二段,第二句(尽管不在他们的表中)中讨论它。

MSDN直到页面中间才讨论二进制标志。

OpenGroup提到了“b”标签的存在,但声明它“应该没有效果”。

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

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

另外值得注意的是,简单地将binmode.obj包含在您的链接命令中将为您执行此操作以打开所有文件。

基于之前答案的解决方案:

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