Инициализация 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.

Другие вопросы по тегам