为什么 fread 提前到达 EOF?

发布于 2024-07-05 21:14:25 字数 1322 浏览 7 评论 0原文

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

循环运行一次,然后由于到达 EOF 而结束(没有错误)。 最后,bytesRead = 10624,ftell(stream) = 28726,缓冲区包含 28726 个值。 我预计当达到 EOF 时,fread 会读取 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”就是答案。 寻求白痴徽章的提名。 :-)

此参考在第二段第二句中讨论了它(尽管不在他们的表中)。

MSDN 直到中途才讨论二进制标志往下翻页。

OpenGroup 提到了“b”标签的存在,但声明它“不会有任何影响”。

I am writing a C library that reads a file into memory. It skips the first 54 bytes of the file (header) and then reads the remainder as data. I use fseek to determine the length of the file, and then use fread to read in the file.

The loop runs once and then ends because the EOF is reached (no errors). At the end, bytesRead = 10624, ftell(stream) = 28726, and the buffer contains 28726 values. I expect fread to read 30,000 bytes and the file position to be 30054 when EOF is reached.

C is not my native language so I suspect I've got a dumb beginner mistake somewhere.

Code is as follows:

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

Depending on the reference you use, it's quite apparent that adding a "b" to the mode flag is the answer. Seeking nominations for the bonehead-badge. :-)

This reference talks about it in the second paragraph, second sentence (though not in their table).

MSDN doesn't discuss the binary flag until halfway down the page.

OpenGroup mentions the existance of the "b" tag, but states that it "shall have no effect".

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

第七度阳光i 2024-07-12 21:14:25

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

Also worth noting that simply including binmode.obj into your link command will do this for you for all file opens.

凡尘雨 2024-07-12 21:14:25

根据之前的答案,解决方案:

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

A solution, based on the previous answers:

    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;
}
幸福不弃 2024-07-12 21:14:25

也许这是二进制模式的问题。 尝试使用 "r+b" 作为模式打开文件。

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

perhaps it's a binary mode issue. Try opening the file with "r+b" as the mode.

EDIT: as noted in a comment "rb" is likely a better match to your original intent since "r+b" will open it for read/write and "rb" is read-only.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文