从流和缓冲区填充矢量时会产生不同的结果

Different results when populating a vector from a stream and a buffer

本文关键字:结果 缓冲区 填充      更新时间:2023-10-16

我有一个二进制文件,正在加载到字节向量中,根据读取文件的方式,我意外地得到了不同的结果。我怀疑这与我使用istream_iterator有关,但我想更好地了解发生了什么。通过后台的方式,加载的数据只是一个字节流。如果重要的话,我认为可能的话,最后十几个左右的字节是0x00。

案例1

ifstream is("file.dat", ifstream::binary);
vector<uint8_t> v;
v.assign(istream_iterator<uint8_t>(is), istream_iterator<uint8_t>());

情况2

ifstream is("file.dat", ifstream::binary);
vector<uint8_t> v;
is.seekg(0, in.end);
int length = is.tellg();
is.seekg(0, in.beg);
char* buffer = new char[length];
is.read(buffer, length);
v.assign(buffer, buffer + length);

情况1导致向量较小。两个向量中的初始数据是相同的,但在情况1中它被截断。

Vlad提供了代码#1的改进版本,我将提供更好的代码#2:

basic_filebuf<uint8_t> ifb;
ifb.open("file.dat", ios_base::in | ios_base::binary);
vector<uint8_t> v;
v.resize(ifb.pubseekoff(0, ios_base::end));
ifb.pubseekpos(0);
ifb.sgetn(&v[0], v.size());

事实上,ifstream并不用于处理未格式化的数据,即使使用ios_base::binary打开它也是如此。该标志有点命名错误——它禁用换行转换,但不会导致插入和提取操作使用二进制编码。

这个版本应该快得多,这不仅是因为在预分配向量时复制较少,而且是因为filebuf xsgetn可以预期传输大块,而迭代器访问单个元素。即使有一个缓冲区用于在I/O级别进行大块传输,迭代器强加的每个字符的虚拟调用也会影响性能。

尝试以下

ifstream is("file.dat", ifstream::binary);
vector<uint8_t> v;
v.assign(istreambuf_iterator<char>(is), istreambuf_iterator<char>());

至于istream_iterator,则使用运算符>>。