【问题标题】:C++ reading buffer sizeC++ 读取缓冲区大小
【发布时间】:2011-06-22 18:42:22
【问题描述】:

假设这个文件有 2 又 1/2 块长,块大小为 1024。

aBlock = 1024;
char* buffer = new char[aBlock];
while (!myFile.eof()) {
    myFile.read(buffer,aBlock);
    //do more stuff
}

第三次读取时,它将写入缓冲区的一半,而另一半则留下无效数据。有没有办法知道它实际写入缓冲区的字节数?

【问题讨论】:

    标签: c++ file-io buffer


    【解决方案1】:

    istream::gcount 返回上一次读取的字节数。

    【讨论】:

    • 引用您的链接:“修改此函数返回值的未格式化输入操作是由以下成员函数执行的操作:get、getline、ignore、peek、read、readsome、putback 和 unget ”。 OP 询问实际写入了多少字节。
    • @yasouser OP 只是使用了令人困惑的术语。从上下文中可以清楚地看出他的意思是读取(如:从文件中读取并写入buffer变量)。
    【解决方案2】:

    您的代码过于复杂且容易出错。

    循环读取并仅检查eof 是一个逻辑错误,因为如果读取时出现错误(无论出于何种原因),这将导致无限循环。

    相反,您需要检查流的所有失败状态,这可以通过简单地检查istream 对象本身来完成。

    由于 read 函数已经返回了它,您可以(并且实际上应该)像这样构造任何读取器循环:

    while (myFile.read(buffer, aBlock))
        process(buffer, aBlock);
    process(buffer, myFile.gcount());
    

    这同时更短,不会隐藏错误并且更具可读性,因为 check-stream-state-in-loop 是一个成熟的 C++ 习惯用法。

    【讨论】:

    • 好的,我以前从来没有这样处理过 C++ 文件。所以那个循环只会读取一个块?
    • @Erandros 该循环将读取尽可能多的块,或者直到到达文件末尾,或者直到读取文件出错(例如,因为用户同时删除了它,或者有设备故障)。
    • 不幸的是,在(正常)文件长度不是块大小的倍数的情况下,您的解决方案会使最终的小块未处理。除非你在循环结束后处理它。由于这个问题,在他再次发布基本相同的问题后,我试图在这里帮助沮丧的提问者 (*.com/questions/6449198/…)。
    • @Bill 是的,循环结束后的处理是隐含的。 ……老实说,我并没有真正想得那么远;上述循环的好处是您根本不必检查循环内的gcount,因此如果您将实际处理交给一个函数,那么上述所有需要的只是一个额外的函数调用结尾。我会修改答案。
    • 两年半过去了。那时我没有看到您发布的代码中的值。现在我看到了。真的很简单。
    【解决方案3】:

    您还可以查看istream::readsome,它实际上返回读取的字节数。

    【讨论】:

    • 然而,这个函数有根本不同的语义。它只会读取与流关联的当前缓冲区。