16

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

virtual void setBlob(unsigned int parameterIndex, std::istream * blob) = 0;

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

如果不复制我的内存块,例如在 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

4 回答 4

48

实际上,编写一个使用缓冲区作为“正确的事情”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();
}
于 2009-09-19T21:08:19.457 回答
9

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

 istrstream( char* pch, int nLength );

这个类有点贬值,或者至少你通常被告知要使用其他类。
strstream 的问题在于管理 char* 缓冲区的内存更为复杂,因此通常您更喜欢 stringstream,因为它为您进行内存管理。但是在这种情况下,您已经在管理 char* 的内存,因此在这种情况下,正常的好处是成本。事实上,在这种情况下,strstream 正是您想要的,代码或速度开销最小。这类似于Herb Sutter 对 ostrsteram的讨论

于 2009-09-19T12:39:14.790 回答
5

Boost.IOStreams 有一个像字符串流一样工作的流,但包装了一个原生数组,因此您不必复制数据。

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

于 2009-09-19T12:47:44.147 回答
-1

未经测试,但也许值得一试...

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

然后用 ss 调用那个 setBlob 函数。您仍然在 std::stringstream 中拥有那个内部缓冲区,因为 jalf 已经提到过。

于 2009-09-19T18:45:43.963 回答