инициализация C ++ std::istringstream из буфера в памяти?
Вопрос
У меня есть блок памяти (непрозрачный), который я хочу сохранить в виде большого двоичного объекта в MySQL через их адаптер C ++.Адаптер ожидает, что istream:
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);
Это правильный путь?
Решение
Посмотрите на std::istrstream, в нем есть конструктор
istrstream( char* pch, int nLength );
Этот класс в некотором роде обесценился или, по крайней мере, вам обычно говорят использовать другие классы.
Проблема с strstream заключается в том, что сложнее управлять памятью буфера char *, поэтому в целом вы бы предпочли stringstream, поскольку он выполняет управление памятью за вас.Однако в этом случае вы уже управляете памятью символа *, так что обычной выгодой в данном случае является стоимость.Фактически, в этом случае 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 есть поток, который работает как stringstream, но обертывает собственный массив, поэтому вам не нужно копировать данные.
std::stringstream всегда создает свой собственный внутренний буфер
Непроверенный, но, возможно, стоит проверить...
std::stringstream ss;
ss.write( blockPtr, blockLength );
ss.seekg(0);
Затем вызовите эту функцию setBlob с помощью ss.У вас все еще есть этот внутренний буфер в std::stringstream, как уже упоминал jalf.