.NET zlib Stream совместим с Actionscript ByteArray.uncompress - PullRequest
6 голосов
/ 10 октября 2009

Не получается получить поток, который Flex 3 хочет распаковать.

Я пробовал:

  • System.IO.Compression.GZipStream
  • System.IO.Compression.DeflateStream
  • ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream
  • zlib.ZOutputStream

Ничто из этого не делает ByteArray.uncompress счастливым, т.е. я получаю

Ошибка # 2058: при распаковке данных произошла ошибка.

Также весь Deflate vs zlib заставляет меня ходить кругами.

Похоже, что согласно статье wikipedia , zlib является реализацией DEFLATE. Но согласно Actionscript это две разные вещи?

Microsoft также указывает, что Gzip, по крайней мере, использует алгоритм Deflate, поскольку в своих документах они ссылаются на то, что GZipOutputStream использует тот же алгоритм сжатия, что и DeflateStream . Поэтому я предполагаю, что это просто разница заголовка, которая указывает, что это «не хорошо», поскольку «ByteArray.uncompress», поскольку алгоритм «DEFLATE» поддерживается только в приложениях AIR.

Пример кода «сервера», в данном случае используется SharpZipLib (не работает):

    public virtual bool ProcessRequest(string path, HttpListenerContext context)
    {
        var buffer = File.ReadAllBytes(path);
        // Specifying to strip header/footer from data as that seems to be what the
        // docs for ByteArray.uncompress indicate is necessary 
        var deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true); 
        using (var zipStream = new DeflaterOutputStream(context.Response.OutputStream, deflater))
        {
            zipStream.Write(buffer, 0, buffer.Length);
        }
    }

Ответы [ 2 ]

11 голосов
/ 12 октября 2009

ZLIB и DEFLATE - это не одно и то же. В RFC IETF определен набор из 3 связанных спецификаций сжатия:

Все они используют (в основном) определенный алгоритм сжатия, который является DEFLATE.

Как ZLIB относится к DEFLATE

Первый, ZLIB, включает кадрирующие байты в начале. Согласно RFC 1950 ...

  A zlib stream has the following structure:

       0   1
     +---+---+
     |CMF|FLG|   (more-->)
     +---+---+

  (if FLG.FDICT set)

       0   1   2   3
     +---+---+---+---+
     |     DICTID    |   (more-->)
     +---+---+---+---+

     +=====================+---+---+---+---+
     |...compressed data...|    ADLER32    |
     +=====================+---+---+---+---+

CMF и FLG - байты. Как сказано в спецификации, метод сжатия primary , используемый в ZLIB, - это DEFLATE, хотя спецификацию можно использовать с другими методами. В общем, это не так. Кроме того, DICTID обычно используется , а не . Поэтому каждый поток ZLIB имеет 2 байта, за которыми следует поток сжатых данных, а затем контрольная сумма Adler32. Сжатые данные представляют собой чистый поток байтов из DEFLATE.

Как GZIP относится к DEFLATE

Это заботится о том, как ZLIB отличается от DEFLATE как формат. GZIP - это третий формат. Если вы хотите узнать подробности, проверьте RFC. Ключевым моментом является то, что, как и ZLIB, GZIP в основном использует DEFLATE и ставит заголовок перед сжатым потоком данных, а затем контрольную сумму. Но заголовок GZIP отличается от заголовка ZLIB, поэтому любой класс GZipStream не сможет записать поток байтов, который будет читаться как ZLIB. И наоборот.

Решение проблемы

Когда читает Поток ZLIB, некоторые люди решают проблему, с которой вы столкнулись , используя встроенный в .NET DeflateStream для потока данных, после продвижения потока после первых двух кадров ZLIB байт. Это работает, пока вы хотите ПРОЧИТАТЬ, поток ZLIB использует DEFLATE (безопасное предположение), и он не определяет фиксированный словарь (также довольно безопасный), и если вам не нужна проверка целостности, предоставляемая Adler32 ( может быть).

Если вам не нравится делать эти предположения или отказываться от проверки, или если вам нужно генерировать поток данных ZLIB, есть ZlibStream в DotNetZip , который будет читать и записывать потоки данных ZLIB для вас, а также проверять или производить контрольную сумму по мере необходимости.

DotNetZip бесплатен, работает с любым языком .NET. Вам не нужна полная библиотека DotNetZip, вместо этого вам просто нужен Ionic.Zlib.dll.

2 голосов
/ 12 октября 2009

Попробуйте использовать System.IO.Compression.DeflateStream или ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream. Вы получите поток DEFLATE.

В конце ActiveScript используйте распаковку с параметром «deflate»: uncompress(CompressionAlgorithm.DEFLATE), как предполагает документация ActiveScript. По умолчанию ActiveScript ожидает поток ZLib, который имеет дополнительную информацию по сравнению с потоком DEFLATE.

...