2012-03-26 55 views
2

我正在做两个框架(OpenSceneGraph和wxWidgets)之间的内存中图像转换。不想关心底层类(osg::ImagewxImage),我用的是面向流的I/O功能都API提供了像这样:基于std :: vector创建std :: stringbuf <char>

1)创建std::stringstream

2)写入使用流OSG的作家

3)使用wxWigdets读者

这工作得相当好从流中读取。到目前为止,我一直使用直接访问流缓冲区,但最近我的注意力被std::stringstream的“非连续底层缓冲区”问题所捕获。我一直在使用kludge来获得一个const char* ptr到缓冲区 - 但它工作(在Windows,Linux和OSX上使用MSVC 9和GCC 4.x进行测试),所以我从来没有修复它。

现在我明白,这段代码是一个定时炸弹,我想摆脱它。这个问题已经在SO(here for instance)上提出过好几次了,但是我找不到能够帮助我做最简单的事情的答案。

我认为最合理的做法是在后台使用矢量创建自己的streambuf - 这可以保证缓冲区是连续的。我知道,这将不是一个通用的解决方案,但给我的限制:

1)所需的大小是无限,实际上相当明确

2)我流真正需要的是一个std::iostream(我不能使用原始字符数组)因为API

任何人都知道我可以如何使用一个字符向量的自定义字符串?请不要回答“使用std::stringstream::str()”,因为我知道我们可以,但我正在寻找其他东西(即使您认为复制2-3 MB太快,我甚至不会注意到差异,让我们考虑一下,我仍然对自定义stringbufs感兴趣,只是为了练习的美丽)。

回答

3

如果你可以只使用一个istreamostream(而不是 双向),并且不需要寻找,这是很简单的(代码10 线)使用std::vector<char>创建自己的streambuf。 但是,除非字符串非常非常大,为什么呢? C++ 11标准 保证std::string是连续的;那 得到的&myString[0]可以用来作为C风格的数组。“并且 之所以加上C++ 11的这个保证,是为了认识现有的 的做法;那里根本没有任何实现,这不是 的情况(现在,它是必需的,在未来不会有任何实现在 的情况下)。

+0

我不确定我是否理解您的答案。关于仅使用istream/ostream:一个插件需要看到一个ostream,而另一个需要看到一个ostream。也许我可以使用相同的基础矢量构建其中的每一个?关于使用std :: string:好的,但是如何从字符串中创建流? – Tibo 2012-03-26 08:57:32

+0

@如果一个插件需要一个ostream,另一个需要一个istream,那么你可能不得不做一些双向的事情。或者,如果他们不同时需要它们,则先使用相同的缓冲区先创建一个ostream,然后创建istream。至于流出字符串的流:'std :: [io] stringstream'已经存在。 – 2012-03-26 09:47:25

+0

您的意思是说,根据C++ 11,std :: stringstream的缓冲区保证是连续的吗?无处可以读取std :: stringstreams内部使用std :: strings - 任何指针? – Tibo 2012-03-26 11:41:25

1

boost :: iostreams有一些现成的接收器。有array_sink,如果你有某种上限,可以预先分配块,这样一个接收器不会动态增长,但另一方面,也可以是积极的。还有back_inserter_device,这是更通用的,并与std::vector直接工作。使用back_inserter_device的示例:

#include <string> 
#include <iostream> 
#include "boost/iostreams/stream_buffer.hpp" 
#include "boost/iostreams/device/back_inserter.hpp" 
int main() 
{ 
    std::string destination; 
    destination.reserve(1024); 
    boost::iostreams::stream_buffer< boost::iostreams::back_insert_device<std::string> > outBuff((destination)); 
    std::streambuf* cur = std::cout.rdbuf(&outBuff); 
    std::cout << "Hello!" << std::endl; 
    // If we used array_sink we'd need to use tellp here to retrieve how much we've actually written, and don't forgot to flush if you don't end with an endl! 
    std::cout.rdbuf(cur); 
    std::cout << destination; 
} 
+0

谢谢。我没有在这个项目中使用增强功能,但会将您的解决方案放在枕头之下供未来使用。 – Tibo 2012-03-26 11:38:39

相关问题