Прочитайте N байтов из файла и добавьте их в std::vector

Я хочу прочитать N байт данных из файлового потока и добавить их в вектор. Итак, допустим, у нас есть

basic_ifstream<uint8_t> myFileStream;

и

vector<uint8_t> myBuffer;

В настоящее время я делаю что-то вроде этого:

myBuffer.reserve(N);
for (int i=0; i<N; ++i)
{
    uint8_t tmpByte;
    myFileStream.read(&tmpByte, 1);
    myBuffer.push_back(tmpByte);
}

но это очень медленно.

Теперь я попытался разрешить myFileStream.read копировать данные прямо в вектор. Поскольку вектор хранит свои элементы в непрерывном месте хранения, я подумал, что что-то вроде этого должно быть возможно:

uint8_t* ptr = &myBuffer.back(); // there is already some elements in the buffer (I know)
ptr++; // first element after existing data
myBuffer.resize(myBuffer.size() + N);
myFileStream.read(ptr, N);

Но при этом я получаю ошибку времени выполнения (повреждение кучи). Что не так с этим решением? Или есть лучший способ сделать это в любом случае?


person Robert Hegner    schedule 09.09.2011    source источник


Ответы (1)


Ваша проблема в том, что resize может потребоваться перераспределить весь вектор и, таким образом, сделать недействительным ваш предыдущий ptr. Указатель нужно брать только после resize.

std::size_t oldSize = myBuffer.size();
// resize first
myBuffer.resize(oldSize + N);
uint8_t* ptr = &myBuffer[oldSize]; // already first element after existing data
myFileStream.read(ptr, N);

Обратите внимание, что в качестве бонуса эта реализация будет работать, даже если исходный вектор пуст (конечно, для N != 0).

person R. Martinho Fernandes    schedule 09.09.2011
comment
@Ajeet: reserve() не меняет size() контейнера. Я ценю правильность выше производительности. - person R. Martinho Fernandes; 10.09.2011
comment
Истинный. Это было бы полезно, только если бы он использовал push_back(). Удаление моего комментария. Спасибо @Р. Мартиньо - person Ajeet Ganga; 10.09.2011
comment
Одно предостережение: если read в конечном итоге читает меньше N байтов, вы захотите изменить размер до любого значения этого счетчика. Вы можете использовать gcount(), чтобы получить количество прочитанных байтов. - person splicer; 24.02.2019