инициализация C ++ std::istringstream из буфера в памяти?

StackOverflow https://stackoverflow.com/questions/1448467

  •  11-09-2019
  •  | 
  •  

Вопрос

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top