2016-05-06 40 views
10

我想复制有效的std::streambuf实例之间的数据。也就是说,我想铲除它们之间的数据块,而不是逐字符复制。例如,这是不是我在寻找:流缓冲区之间的数据的块级复制

stringbuf in{ios_base::in}; 
stringbuf out{ios_base::out}; 
copy(istreambuf_iterator<char>{in}, 
    istreambuf_iterator<char>{}, 
    ostreambuf_iterator<char>{out}); 

存在着这种语法糖,有一点错误检查:

ostream os{&out}; 
os << &in; 

这里是operator<<(basic_streambuf<..>*)实施的一个片段在我的标准库(Mac OS X,XCode 7)中:

   typedef istreambuf_iterator<_CharT, _Traits> _Ip; 
       typedef ostreambuf_iterator<_CharT, _Traits> _Op; 
       _Ip __i(__sb); 
       _Ip __eof; 
       _Op __o(*this); 
       size_t __c = 0; 
       for (; __i != __eof; ++__i, ++__o, ++__c) 
       { 
        *__o = *__i; 
        if (__o.failed()) 
         break; 
       } 

底线是:这仍然是每个字符复制。我希望标准库使用的算法依赖于流缓冲区的块级成员函数sputnsgetn,而不是每个字符的传输。标准库是否提供了这样的算法,还是必须推出自己的算法?

+3

的问题的输出是,这是基于与虚拟功能的接口上。你永远不知道什么时候'* __ o = * __ i''将无法输出,所以你不能提前阅读并且有可能失去这些角色。 –

+0

你找到了方法吗? – barney

回答

1

恐怕答案是:目前标准库的设计是不可能的。原因是流缓冲区完全隐藏了它们管理的字符序列。这使得不可能将字节从一个流缓冲区的get区域直接复制到另一个缓冲区的放置区域。

如果“输入”流缓冲区会暴露其内部缓冲区,那么“输出”流缓冲区可以使用sputn(in.data(), in.size())。或者更明显的是:如果输出缓冲区还暴露了其内部缓冲区,那么可以使用普通的memcpy铲除两者之间的字节。其他I/O库以这种方式运行:例如Google协议缓冲区的stream implementation。 Boost IOStreams有optimized implementation to copy between streams。在这两种情况下,高效的块级复制都是可能的,因为等效的流缓冲区提供对中间缓冲区的访问。具有讽刺意味的是,流缓冲区甚至不需要缓冲区:当操作无缓冲区时,每个读/写操作都会直接传送到底层设备。据推测,这是标准库不支持内省的原因之一。不幸的是,输入和输出流缓冲之间没有有效的复制是可能的。块级复制需要一个中间缓冲区,复制算法的操作如下:

  1. 通过sgetn将输入流缓冲区读入中间缓冲区。
  2. 通过sputn从中间缓冲区写入输出流缓冲区。
  3. 转到1.直到输入信息已耗尽或写入失败streambuffer