Инициализация C++ std::istringstream из буфера в памяти?
У меня есть блок памяти (непрозрачный), который я хочу сохранить в BLOB-объекте в MySQL через их адаптер C++. Адаптер ожидает поток:
virtual void setBlob(unsigned int parameterIndex, std::istream * blob) = 0;
Поэтому мой вопрос: как я могу создать std:: istream из этого блока памяти (напечатанного как char*). Это не строка, так как она не заканчивается нулем (но я знаю ее длину, конечно).
Я не мог найти способ сделать это без копирования моего блока памяти, например, в std:: string. Я думаю, что это немного расточительно. Что-то вроде этого не работает:
std::streambuf istringbuf(blockPtr, blockLength);
std::istringstream tmp_blob(&istringbuf);
потому что std:: streambuf не имеет такого конструктора. Я видел следующее предложение.
std:: istringstream tmp_blob;
tmp_blob.rdbuf()->pubsetbuf(blockPtr, blockLength);
Это правильный путь?
4 ответа
Посмотрите на std::istrstream, у него есть конструктор
istrstream( char* pch, int nLength );
Этот класс является устаревшим или, по крайней мере, вам обычно говорят использовать другие классы.
Проблема с strstream заключается в том, что управлять памятью буфера char* сложнее, поэтому в целом вы бы предпочли stringstream, поскольку он выполняет управление памятью за вас. Однако в этом случае вы уже управляете памятью char*, поэтому обычное преимущество в этом случае - стоимость. На самом деле в этом случае strstream делает именно то, что вам нужно, с минимальными затратами кода или скорости. Это похоже на обсуждение остстрэстера Хербом Саттером
Это на самом деле довольно тривиально, чтобы написать один выстрел std::streambuf
который использует буфер в качестве поведения по умолчанию для всех виртуальных функций std::streambuf
делает "правильные вещи". Вы можете просто setg
область чтения в строительстве и underflow
а также uflow
можно смело возвращаться traits_type::eof()
как конец начальной области получения - это конец потока.
например:
#include <streambuf>
#include <iostream>
#include <istream>
#include <ostream>
struct OneShotReadBuf : public std::streambuf
{
OneShotReadBuf(char* s, std::size_t n)
{
setg(s, s, s + n);
}
};
char hw[] = "Hello, World!\n";
int main()
{
// In this case disregard the null terminator
OneShotReadBuf osrb(hw, sizeof hw - 1);
std::istream istr(&osrb);
istr >> std::cout.rdbuf();
}
Boost.IOStreams имеет поток, который работает как строковый поток, но оборачивает собственный массив, поэтому вам не нужно копировать данные.
std:: stringstream всегда создает свой внутренний буфер
Не проверено, но, возможно, стоит проверить...
std::stringstream ss;
ss.write( blockPtr, blockLength );
ss.seekg(0);
Затем вызовите эту функцию setBlob с помощью ss. У вас все еще есть этот внутренний буфер в std::stringstream, как уже упоминалось в jalf.