инициализация C ++ std :: istringstream из буфера в памяти? - PullRequest
13 голосов
/ 19 сентября 2009

У меня есть блок памяти (непрозрачный), который я хочу сохранить в 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 ]

41 голосов
/ 20 сентября 2009

На самом деле довольно просто написать один кадр 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();
}
8 голосов
/ 19 сентября 2009

Посмотрите на std :: istrstream, у него есть конструктор

 istrstream( char* pch, int nLength );

Этот класс является устаревшим или, по крайней мере, вам обычно говорят, что вы используете другие классы.
Проблема с strstream заключается в том, что управлять памятью буфера char * сложнее, поэтому в целом вы предпочитаете stringstream, так как он выполняет управление памятью за вас. Однако в этом случае вы уже управляете памятью char *, поэтому обычное преимущество в этом случае - стоимость. На самом деле в этом случае strstream делает именно то, что вам нужно, с минимальными затратами кода или скорости. Это похоже на обсуждение ostrsteram Хербом Саттером

5 голосов
/ 19 сентября 2009

Boost.IOStreams имеет поток, который работает как поток строк, но переносит собственный массив, поэтому вам не нужно копировать данные.

std :: stringstream всегда создает собственный внутренний буфер

0 голосов
/ 19 сентября 2009

Не проверено, но, возможно, стоит проверить ...

std::stringstream ss;
ss.write( blockPtr, blockLength );
ss.seekg(0);

Затем вызовите эту функцию setBlob с помощью ss. У вас все еще есть этот внутренний буфер в std :: stringstream, как уже упоминалось в jalf.

...