代码之家  ›  专栏  ›  技术社区  ›  James Schek

为什么氟利昂要提前到达EOF?

  •  27
  • James Schek  · 技术社区  · 16 年前

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

    循环运行一次,然后结束,因为已达到EOF(无错误)。最后,bytesread=10624,ftell(stream)=28726,缓冲区包含28726个值。我预计fread将读取30000字节,当达到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”是答案。正在为“笨蛋”徽章寻求提名。-)

    This reference 在第二段,第二句话(尽管没有在他们的表格中)中谈论它。

    MSDN 直到下半页才讨论二进制标志。

    OpenGroup 提及“B”标签的存在,但声明其“无效”。

    3 回复  |  直到 9 年前
        1
  •  52
  •   Evan Teran    13 年前

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

    编辑 :如注释所述 "rb" 可能更符合你的初衷,因为 “R+B” 将打开它进行读/写 “RB” 是只读的。

        2
  •  0
  •   Richard Harrison    16 年前

    同样值得注意的是,只要将binmode.obj包含到您的link命令中,就可以为所有打开的文件做到这一点。

        3
  •  -1
  •   Brad Larson    9 年前

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

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