.NET zlib流与Actionscript ByteArray.uncompress兼容。

6
我似乎无法获取Flex 3想要解压缩的流。
我尝试过:
  • System.IO.Compression.GZipStream
  • System.IO.Compression.DeflateStream
  • ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream
  • zlib.ZOutputStream

这些都似乎无法让ByteArray.uncompress满意,即我收到以下错误:

错误#2058:解压数据时出错。

此外,Deflate和zlib的整个问题让我感到困惑。

根据wikipedia文章,zlib是DEFLATE的一种实现。但是根据Actionscript,它们是两个不同的东西?

微软似乎也表明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);
        }
    }

不确定C#,但我知道ByteArray.uncompress()可以完美处理使用Python内置的zlib库压缩的数据... - Cameron
没有,由于问题让我感到沮丧,我放弃了今晚的工作。我打算尝试重现最简单的情况,看看是否还有其他问题。 - Joseph Kingry
你是如何在AS3端从服务器读取它的?你是将其作为UTF8字符串通过服务器发送的吗? - Jón Trausti Arason
2个回答

11

ZLIB和DEFLATE不是同一个东西。在IETF RFC中定义了一组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是字节。正如规范所说,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数据流,则DotNetZip中有一个ZlibStream可以为您读取和写入ZLIB数据流,并根据需要验证或生成校验和。
DotNetZip可免费使用,适用于任何.NET语言。 您不需要完整的DotNetZip库,而只需要Ionic.Zlib.dll。

2

尝试使用 System.IO.Compression.DeflateStream 或者 ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream。你将获得 DEFLATE 流。

在 ActiveScript 结束时,使用参数为 "deflate" 的 uncompress 方法:uncompress(CompressionAlgorithm.DEFLATE),正如 ActiveScript 文档建议的那样。默认情况下,ActiveScript 期望一个 ZLib 流,相对于 DEFLATE 流,它带有额外的信息。


DEFLATE 只能在 Air 应用程序中使用,这对我的情况不起作用。 - Joseph Kingry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接