【问题标题】:initializing a C++ std::istringstream from an in memory buffer?从内存缓冲区初始化 C++ std::istringstream?
【发布时间】:2010-11-29 17:26:30
【问题描述】:

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

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

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

如果不复制我的内存块,例如在 std::string 中,我无法找到一种方法。我觉得这有点浪费。像这样的东西不起作用:

    std::streambuf istringbuf(blockPtr, blockLength);
    std::istringstream tmp_blob(&istringbuf);

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

    std:: istringstream       tmp_blob;
    tmp_blob.rdbuf()->pubsetbuf(blockPtr, blockLength);

这是正确的方法吗?

【问题讨论】:

标签: c++ streambuf


【解决方案1】:

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

 istrstream( char* pch, int nLength );

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

【讨论】:

  • 是的,但是 Josuttis 说“保留 char* 流类只是为了向后兼容。它们的接口容易出错,而且很少被正确使用。”这就是为什么我有点不愿意使用它们的原因。而“仅为向后兼容而保留”似乎意味着使用“更好”的类有更好的方法。
  • 我读过那篇文章,它直接相关。谢谢。我想我的问题得到了回答,尽管没有评论“tmp_blob.rdbuf()->pubsetbuf(blockPtr, blockLength);”接近。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

      编写一个一次性的std::streambuf 实际上非常简单,它使用适当的缓冲区作为std::streambuf 的所有虚函数的默认行为,“做正确的事”。你可以在构造中只setg读取区域,underflowuflow可以安全地返回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();
      }
      

      【讨论】:

      猜你喜欢
      • 2016-02-04
      • 1970-01-01
      • 2020-01-08
      • 2014-12-01
      • 2023-03-19
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多