Flushing a boost::iostreams::zlib_compressor. How to obtain a “sync flush”?

落花浮王杯 提交于 2020-01-03 11:54:53

问题


Is there some magic required to obtain a "zlib sync flush" when using boost::iostreams::zlib_compressor ? Just invoking flush on the filter, or strict_sync on a filtering_ostream containing it doesn't see to do the job (ie I want the compressor to flush enough that the decompressor can recover all the bytes consumed by the compressor so far, without closing the stream).

Looking at the header, there seem to be some "flush codes" defined (notably a sync_flush) but it's unclear to me how they should be used (bearing in mind my compressor is just added into a filtering_ostream).


回答1:


It turns out there is a fundamental problem that the symmetric_filter that zlib_compressor inherits from isn't itself flushable (which seems rather an oversight).

Possibly adding such support to symmetric_filter would be as simple as adding the flushable_tag and exposing the existing private flush methods, but for now I can live with it.




回答2:


This C++ zlib wrapper library, of which I'm the author, supports flush functionality and is arguably simpler to use:

https://github.com/rudi-cilibrasi/zlibcomplete

It is as easy as this:

#include <iostream>
#include <zlc/zlibcomplete.hpp>

using namespace zlibcomplete;
using namespace std;

int main(int argc, char **argv)
{
  const int CHUNK = 16384;
  char inbuf[CHUNK];
  int readBytes;
  ZLibCompressor compressor(9, auto_flush);
  for (;;) {
    cin.read(inbuf, CHUNK);
    readBytes = cin.gcount();
    if (readBytes == 0) {
      break;
    }
    string input(inbuf, readBytes);
    cout << compressor.compress(input);
  }
  cout << compressor.finish();
  return 0;
}

The main difference from boost is that instead of using a template class filter you simply pass in a string and write out the compressed string that results as many times as you want. Each string will be flushed (in auto_flush mode) so it can be used in interactive network protocols. At the end just call finish to get the last bit of compressed data and a termination block. While the boost example is shorter, it requires using two other template classes that are not as well-known as std::string, namely filtering_streambuf and the less-standard boost::iostreams:copy. The boost interface to zlib is incomplete in that it does not support Z_SYNC_FLUSH. This means it is not appropriate for online streaming applications such as in TCP interactive protocols. I love boost and use it as my main C++ support library in all of my C++ projects but in this particular case it was not usable in my application due to the missing flush functionality.



来源:https://stackoverflow.com/questions/2468792/flushing-a-boostiostreamszlib-compressor-how-to-obtain-a-sync-flush

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!