从内存缓冲区初始化C++ std :: istringstream?

Jea*_*uys 14 c++ streambuf

我有一个内存块(不透明),我想通过他们的C++适配器存储在mySQL的Blob中.适配器需要一个istream:

virtual void setBlob(unsigned int parameterIndex, std::istream * blob) = 0;
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:如何从这个内存块创建一个std :: istream(键入为char*).它不是一个字符串,因为它不是以空值终止的(但我知道它的长度当然).

如果没有复制我的内存块,例如在std :: string中,我找不到一种方法.我认为这有点浪费.这样的东西不起作用:

    std::streambuf istringbuf(blockPtr, blockLength);
    std::istringstream tmp_blob(&istringbuf);
Run Code Online (Sandbox Code Playgroud)

因为std :: streambuf没有这样的构造函数.我看到了以下建议.

    std:: istringstream       tmp_blob;
    tmp_blob.rdbuf()->pubsetbuf(blockPtr, blockLength);
Run Code Online (Sandbox Code Playgroud)

这是正确的方法吗?

CB *_*ley 41

写一个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();
}
Run Code Online (Sandbox Code Playgroud)


use*_*019 9

看看std :: istrstream它有一个构造函数

 istrstream( char* pch, int nLength );
Run Code Online (Sandbox Code Playgroud)

这个类有点折旧,或者至少你被告知要使用其他类.
strstream的问题是管理char*缓冲区的内存比较复杂,所以一般来说你更喜欢stringstream,因为它为你做了内存管理.但是在这种情况下,您已经在管理char*的内存,因此在这种情况下,正常的好处是成本.事实上,在这种情况下,strstream完全符合您的要求,并且代码或速度的开销最小.这类似于Herb Sutterostrsteram的讨论

  • 是的,但Josuttis说:"char*流类只保留用于向后兼容.它们的界面容易出错,很少使用它们." 这就是为什么我有点不愿意使用它们.并且"仅为了向后兼容而保留"似乎暗示有更好的方法使用"更好"的类. (6认同)

jal*_*alf 5

Boost.IOStreams有一个像stringstream一样工作的流,但包装了一个本机数组,因此你可以避免复制数据.

std :: stringstream总是创建自己的内部缓冲区