使用 istreambuf_iterator 与 copy_n 读取文件

问题描述 投票:0回答:1

我想解析一个文件中不同长度的不同类型的块,所以我创建了一个函数通过传入 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 打开。

c++ stl ifstream
1个回答
0
投票

您正在使用

istreambuf_iterator
。它是一个仅输入迭代器。想象一下,您有一个 5 字节的文件,并且您读取了
count=2
:

  1. 它调用
    sgetc
    来读取第一个字节。这不会提前流位置。
  2. 由于
    count=2
    copy_n
    需要多一个字节。因此它会增加流位置。
  3. 它使用
    sgetc
    读取第二个字节。
  4. count=2
    起,不再需要任何字节。
    copy_n
    回归。

请注意,只有步骤 2 增加了流位置,并且在读取两个字符时只需要调用一次。

是的,这很奇怪。但大多数人只会使用

input_file.read()
。我几乎从未见过人们在生产代码中使用
istreambuf_iterator
...尤其是因为它对于您的用例类型来说效率低下。

© www.soinside.com 2019 - 2024. All rights reserved.