我想解析一个文件中不同长度的不同类型的块,所以我创建了一个函数通过传入 ifstream 来读取块,如下所示:
void parse_next(std::ifstream& input_file, std::vector<uint8_t>& data, size_t count)
{
std::copy_n(
std::istreambuf_iterator<char>(input_file),
count,
std::back_inserter(data)
);
}
我预计文件位置会增加count,即
// some init code
size_t const pos_before{input_file.tellg()};
parse_next(input_file, data, count);
size_t const pos_after{input_file.tellg()};
// this assumption is _not_ correct!
assert(count == (pos_after - pos_before));
// but this is!
assert((count - 1) == (pos_after - pos_before));
但是,使用
input_file.read()
和 count 而不是 std::copy_n
可以给出正确的计数。
那么这是怎么回事?我在 istreambuf_iterator 的文档中看不到任何提到这一点的地方。 还是
std::copy_n
在搞乱我?
请注意,在上面的示例中,我们可以假设还有大量数据需要读取,因此这并不是因为文件为空。 此外,文件以 binary 打开。
您正在使用
istreambuf_iterator
。它是一个仅输入迭代器。想象一下,您有一个 5 字节的文件,并且您读取了 count=2
:
sgetc
来读取第一个字节。这不会提前流位置。count=2
,copy_n
需要多一个字节。因此它会增加流位置。sgetc
读取第二个字节。count=2
起,不再需要任何字节。 copy_n
回归。请注意,只有步骤 2 增加了流位置,并且在读取两个字符时只需要调用一次。
是的,这很奇怪。但大多数人只会使用
input_file.read()
。我几乎从未见过人们在生产代码中使用 istreambuf_iterator
...尤其是因为它对于您的用例类型来说效率低下。