Дефлирование данных из формата MSZIP

Я пытаюсь прочитать сжатый двоичный файл сетки .x, но моя распаковка не удалась. Файл в основном представляет собой некоторую информацию о заголовке DirectX, а затем набор данных в формате MSZIP (т.е. 2 байта - это int blockSize, 2 байта - это «магическое число», а затем есть blockSize дефлированные байты, а затем повторяются, пока не будет больше данных) поэтому для каждого блока я просто получаю сжатые байты и выкачиваю их так:

internal static byte[] DecompressBlock(byte[] data) {
    var result = new List<byte>();
    var ms = new MemoryStream(data);
    var ds = new DeflateStream(ms, CompressionMode.Decompress);
    var newStream = new MemoryStream();
    ds.CopyTo(newStream);
    ds.Flush();
    ds.Close();
    return newStream.GetBuffer();
}

Первый блок сдувается, как и ожидалось. Последующие блоки имеют правильный увеличенный размер, но, по-видимому, случайно, некоторые байты равны 0, когда они не должны быть, обычно в группах по 4-12.

Как я могу выкачать разные блоки заархивированных данных, сохраняя при этом один и тот же буфер истории?

ОБНОВЛЕНИЕ: после небольшого дополнительного исследования похоже, что при сжатии MSZIP эти блоки ЯВЛЯЮТСЯ результатами отдельных операций выкачивания, но между ними сохраняется «буфер истории». Я не знаю, сможет ли deflatestream справиться с этим. обновил актуальный вопрос


person Ross Manson    schedule 08.09.2016    source источник


Ответы (1)


Да, есть что-то, чего вам не хватает. Каждый блок deflate может использовать и использует историю из предыдущего блока deflate. Таким образом, в каждом блоке вы должны инициализировать словарь deflate последними 32 КБ несжатых данных из предыдущих блоков.

person Mark Adler    schedule 08.09.2016
comment
Спасибо! Я не видел этого, пока не обновил вопрос. Я не думаю, что вы знаете, как это сделать на С#, не так ли? - person Ross Manson; 08.09.2016
comment
Похоже, что класс Deflate не предоставляет доступ к функции deflateSetDictionary() zlib. Вам нужно будет использовать zlib напрямую. - person Mark Adler; 08.09.2016
comment
На самом деле, если вы используете zlib напрямую, вы можете использовать недокументированную функцию deflateResetKeep(), которую я добавил только для этой цели. Он запускает новый поток дефляции, но сохраняет словарь из только что завершенной дефляции, используя это состояние. Существует также соответствующий inflateResetKeep(). - person Mark Adler; 08.09.2016
comment
Спасибо! НУЖНО БОЛЬШЕ ПЕРСОНАЖЕЙ ДЛЯ КОММЕНТАРИЙ - person Ross Manson; 08.09.2016