【问题标题】:Is GZipStream header reliable across .NET versions?GZipStream 标头在 .NET 版本中是否可靠?
【发布时间】:2015-07-28 15:57:17
【问题描述】:

我来到 Q&A Is there a way to know if the byte[] has been compressed by gzipstream? 并且一些作者说(这是真的)GZipStream{0x1f, 0x8b, 8, 0, 0, 0, 0, 0, 4, 0} 字符作为标题来了解字节数组是否是压缩字符串。

我的问题是,GZipStream 标头跨 .NET 版本是否可靠?

【问题讨论】:

    标签: c# .net gzip gzipstream


    【解决方案1】:

    任何 GZip 格式的流都可以保证:

    前两个字节:1f8b

    下一个字节:00 用于存储(无压缩),01 用于压缩算法,02 用于打包,03 用于 lzf,08 用于放气。到目前为止,.NET 始终使用 deflate 并且许多情况只需要 deflate(Web 客户端只期望基于 deflate 的 gzip 作为传输或标记为 gzip 的内容编码),因此如果没有某种选项,它就不太可能改变指定它被添加。

    接下来是文件类型,00 的意思是“可能是某种文本文件”因为GZipStream 没有关于文件类型的信息,所以它总是使用它。

    接下来的四个是 Unix 格式的文件修改时间。同样,由于该类没有关于文件的信息——因为它接收的是流,而不是带有元数据的文件,所以这些总是设置为 0。

    下一个字节取决于压缩方法。 deflate 可以是2 表示重度压缩或4 表示轻度压缩。

    下一个(序列中的最后一个)取决于使用的操作系统类型。 0 表示“FAT 文件系统”,但随着 Windows 转而使用 NTFS 等其他文件系统,Windows 继续使用它。如果在非 Windows 文件系统上与 Mono 一起使用,它可能具有不同的值,尽管这种情况也可能决定匹配 .NET 行为。 (更新:在非 Windows 系统上,至少某些版本的 Mono 会将文件系统标志设置为 0 以外的值)。

    【讨论】:

    • 根据this link,第三个字节(压缩方式)的值0到7是保留的,只有值8是实际有效的。此链接是否未显示当前信息?
    • 看来我应该接受这个答案,但我更愿意等着看是否没有人提供更多更正
    • @DanielHilgarth GNU GZip 实用程序允许我提到的其他压缩方案,并使用我描述的标志,尽管我不知道有任何标准文档过时 RFC 1952,正如你所说,将它们列为保留。不过,如果您使用 GNU GZip 或与之兼容的任何东西,这些值仍然可以找到。
    • 不,gzip 既不接受也不生成第三个字节中的任何值,但 8.gzip 将解压缩具有不同 前两个字节的 Unix 压缩和 Unix 打包文件,@987654337 @ 用于压缩,0x1f 0x1e 用于打包。当你说“lzf”时,我认为你的意思是 lzh。 gzip 也会解压缩,前两个字节用0x1f 0xa0 标记。
    【解决方案2】:

    它应该是可靠的,因为此标头来自 GZip 规范,因此不是 .NET 特定的。有关这些值的说明,请参阅 here

    然而,根据规范,只有前两个字节实际上总是相同的。第三个字节实际上总是相同的,因为目前只存在一个有效值。以下字节可能会发生变化。

    【讨论】:

    • 如果我更改参数化GZipStream 的方式,它可能会改变,我弄错了吗?
    • 对不起,如果我使用其他类或 lib 使用 gzip 进行压缩,它可能会改变......对吗?
    • 不是前三个字节。但其余的可能会改变,是的
    • 感谢您的努力。可能我会接受另一个答案,因为它提供了更多背景知识,但这并不意味着您的答案不正确。也不错
    • @MatíasFidemraizer:当然,继续。我也会这样做:)
    【解决方案3】:

    确保 gzip 流以 0x1f 0x8b 0x08 开头。除了第三个字节中的0x08,不支持其他压缩方法。

    因此,如果您没有看到 0x1f 0x8b 0x08,那么它不是 gzip 流。但是,如果您确实看到0x1f 0x8b 0x08,那么它可能可能不是是一个gzip流。它可能是,但你不能假设。

    您应该对候选 gzip 文件做的就是简单地开始解压缩它。如果没有 gzip 标头,解码器将立即识别,如果意外出现 gzip 标头,解码器将很快检测到压缩数据中的问题。您不必检查标头,因为解码器已经这样做了,并且在那之后检查有效的压缩数据。

    【讨论】:

    • 虽然您是对的,但检查标头可以避免可预测的异常(所以它毕竟不是那么异常......)。因此,如果问题是数据无效,那么采用您的方法意味着尝试/捕获并静音异常......
    • 异常有什么可怕的?使用该方法可确保它与GZipStream 的任何添加或更改保持同步。
    • 哦哦不!!无休止的讨论! :D 我们可以这样发疯。关于何时抛出和处理异常有很多观点。
    猜你喜欢
    • 2019-02-20
    • 1970-01-01
    • 1970-01-01
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-10
    • 2020-08-13
    相关资源
    最近更新 更多