【发布时间】:2019-07-12 22:53:22
【问题描述】:
我正在尝试分块读取二进制文件。该文件大约为 11 kB。以下代码仅从文件中读取一次,gcount() 函数表示仅读取了 1015 个字符(字节)并且流“已耗尽”并且 while 循环不会继续(尽管缓冲区已正确填充到 @987654323 @):
std::array<int64_t, 256> HuffmanTree::get_frequencies(std::istream & stream) const
{
const size_t buffer_size = 4096;
unsigned char buffer[buffer_size];
std::array<int64_t, 256> frequencies;
frequencies.fill(0);
while (stream)
{
stream.read((char *)buffer, buffer_size);
std::streamsize bytes_read = stream.gcount();
for (std::streamsize i = 0; i < bytes_read; i++)
{
frequencies[buffer[i]]++;
}
}
return frequencies;
}
是什么导致了这种行为,我该如何解决?
编辑:stream.read(...) 仅调用一次,gcount() 返回 1015。但缓冲区包含文件的前 4096 个字节(我也在 Windows 上运行 - VS 2017)
【问题讨论】:
-
我无法重现。我模拟的输入文件大约为 11 kB,并且该例程能够输入文件的每个字节。我不知道你为什么要为最后一个缓冲区块读取 1015 个字节而不是 ~3072 个字节。如果您在 Windows 上运行,那么我可能会冒险猜测(即 istream 不是二进制模式)。或者如果它是一个输入流,如管道或打开的套接字。
-
那很奇怪。另外问题是 read() 函数只被调用一次,所以我只得到文件的前 4096 个字节,而没有其他任何东西。流结束说它已读取 1015 个字节。但是缓冲区包含文件中的 4096 个字节。文件的其余部分永远不会被读取。还有如何以二进制模式打开 istream?如果输入文件是二进制文件还是文本文件对我无关紧要怎么办?
-
你的平台是什么?您使用的是什么 C++ 编译器?您使用的是什么编译器版本?你能用minimal reproducible example 复制吗?您是否尝试过使用调试器单步执行代码?
-
编辑了问题。我试图逐步完成,那是当我发现 read 函数只被调用一次时。我不明白为什么会发生这种情况(以及为什么它会正确填充缓冲区并说它只读取了 1015 个字节)。
-
"如果输入文件是二进制文件还是文本文件对我来说无关紧要怎么办?"在 Windows 平台上,作为文本处理的文件将处理、解释和翻译字符。可能输入文件在位置 1016 处有一个“文件结尾”字符。