Сброс файла boost::iostreams::zlib_compressor. Как получить синхронизацию?

Нужно ли какое-то волшебство, чтобы получить "синхронный сброс zlib" при использовании < a href="http://www.boost.org/doc/libs/1_41_0/libs/iostreams/doc/classes/zlib.html" rel="noreferrer">boost::iostreams::zlib_compressor ? Простой вызов flush на фильтре или strict_sync на filtering_ostream, содержащем его, не выполняет работу (т.е. я хочу, чтобы компрессор сбрасывал достаточно, чтобы декомпрессор мог восстановить все байты, потребленные компрессором до сих пор, без закрытия потока ).

Глядя на заголовок, кажется, что определены некоторые "коды сброса" (в частности, sync_flush), но мне неясно, как их следует использовать (учитывая, что мой компрессор только что добавлен в filtering_ostream).


person timday    schedule 18.03.2010    source источник


Ответы (2)


Оказывается, существует фундаментальная проблема, заключающаяся в том, что symmetric_filter, от которого наследуется zlib_compressor, сам по себе не сбрасывается (что кажется скорее упущением).

Возможно, добавить такую ​​поддержку в symmetric_filter было бы так же просто, как добавить flushable_tag и открыть существующие методы приватной очистки, но пока я могу с этим смириться.

person timday    schedule 12.04.2010
comment
Вот PR для его добавления: github.com/boostorg/iostreams/pull/116 - хотя, кажется, никто не проверяет это. - person John Zwinck; 28.10.2020

Эта библиотека-оболочка C++ zlib, автором которой я являюсь, поддерживает функциональность флеша и, возможно, проще в использовании:

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

Это так же просто:

#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;
}

Основное отличие от boost заключается в том, что вместо использования фильтра класса шаблона вы просто передаете строку и записываете полученную сжатую строку столько раз, сколько хотите. Каждая строка будет очищена (в режиме auto_flush), чтобы ее можно было использовать в интерактивных сетевых протоколах. В конце просто вызовите finish, чтобы получить последний бит сжатых данных и блок завершения. Хотя пример boost короче, он требует использования двух других классов шаблонов, которые не так хорошо известны, как std::string, а именно filtering_streambuf и менее стандартный boost::iostreams:copy. Интерфейс boost для zlib неполный, поскольку он не поддерживает Z_SYNC_FLUSH. Это означает, что он не подходит для потоковых онлайн-приложений, таких как интерактивные протоколы TCP. Мне нравится boost, и я использую его в качестве основной библиотеки поддержки C++ во всех своих проектах на C++, но в данном конкретном случае его нельзя было использовать в моем приложении из-за отсутствия функции сброса.

person Rudi Cilibrasi    schedule 08.07.2015
comment
Возможно, вы можете продемонстрировать конкретный пример здесь, в StackOverflow, о том, как это, по вашему мнению, как автору библиотеки, проще в использовании? - person Juliën; 08.07.2015
comment
Спасибо, я сделал это, ценю обратную связь. - person Rudi Cilibrasi; 09.07.2015