如何从包含多个 GzipStream 的文件中读取

2023-11-27

我有一个使用代码创建的文件,如下所示:

        using (var fs=File.OpenWrite("tmp"))
        {
            using (GZipStream gs=new GZipStream(fs,CompressionMode.Compress,true))
            {
                using (StreamWriter sw=new StreamWriter(gs))
                {
                    sw.WriteLine("hello ");
                }
            }

            using (GZipStream gs = new GZipStream(fs, CompressionMode.Compress, true))
            {
                using (StreamWriter sw = new StreamWriter(gs))
                {
                    sw.WriteLine("world");
                }
            }
        }

现在我尝试使用以下代码从此文件中读取数据:

        string txt;

        using (var fs=File.OpenRead("tmp"))
        {
            using (GZipStream gs=new GZipStream(fs,CompressionMode.Decompress,true))
            {
                using (var rdr = new StreamReader(gs))
                {
                    txt = rdr.ReadToEnd();
                }
            }

            using (GZipStream gs = new GZipStream(fs, CompressionMode.Decompress, true))
            {
                using (StreamReader sr = new StreamReader(gs))
                {
                    txt+=sr.ReadToEnd();
                }
            }
        }

第一个流读取正常,但第二个流无法读取。

如何读取第二个流?


这是 GzipStream 处理具有多个 gzip 条目的 gzip 文件的方式的问题。它读取第一个条目,并将所有后续条目视为垃圾(有趣的是,gzip 和 winzip 等实用程序通过将它们全部提取到一个文件中来正确处理它)。有几种解决方法,或者您可以使用第三方实用程序,例如点网压缩 (http://dotnetzip.codeplex.com/).

也许最简单的方法是扫描文件中的所有 gzip 标头,然后手动将流移动到每个标头并解压缩内容。这可以通过在原始文件字节中查找ID1、ID2和0x8来完成(Deflate压缩方法,请参阅规范:http://www.gzip.org/zlib/rfc-gzip.html)。这并不总是足以保证您正在查看 gzip 标头,因此您需要读取标头的其余部分(或至少前十个字节)来验证:

    const int Id1 = 0x1F;
    const int Id2 = 0x8B;
    const int DeflateCompression = 0x8;
    const int GzipFooterLength = 8;
    const int MaxGzipFlag = 32; 

    /// <summary>
    /// Returns true if the stream could be a valid gzip header at the current position.
    /// </summary>
    /// <param name="stream">The stream to check.</param>
    /// <returns>Returns true if the stream could be a valid gzip header at the current position.</returns>
    public static bool IsHeaderCandidate(Stream stream)
    {
        // Read the first ten bytes of the stream
        byte[] header = new byte[10];

        int bytesRead = stream.Read(header, 0, header.Length);
        stream.Seek(-bytesRead, SeekOrigin.Current);

        if (bytesRead < header.Length)
        {
            return false;
        }

        // Check the id tokens and compression algorithm
        if (header[0] != Id1 || header[1] != Id2 || header[2] != DeflateCompression)
        {
            return false;
        }

        // Extract the GZIP flags, of which only 5 are allowed (2 pow. 5 = 32)
        if (header[3] > MaxGzipFlag)
        {
            return false;
        }

        // Check the extra compression flags, which is either 2 or 4 with the Deflate algorithm
        if (header[8] != 0x0 && header[8] != 0x2 && header[8] != 0x4)
        {
            return false;
        }

        return true;
    }

请注意,如果直接使用文件流,GzipStream 可能会将流移动到文件末尾。您可能希望将每个部分读入 MemoryStream,然后在内存中单独解压缩每个部分。

另一种方法是修改 gzip 标头以指定内容的长度,这样您就不必扫描文件中的标头(您可以以编程方式确定每个标头的偏移量),这需要更深入地研究gzip 规范

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从包含多个 GzipStream 的文件中读取 的相关文章

随机推荐

  • 迅速。无主相对于弱者的(绝对)唯一的具体优势是性能吗?

    在 Swift 中 我们有正常的默认类型 该对象根本不能变为零 我们有弱类型 该对象可以变为零 如果对象变成nil 你的指针自动变成nil 所以你知道对象变成了nil 我们有无主打字 该对象可以变为零 如果对象变成 nil 你的指针不会发生
  • Gstreamer tcpserversink v0.10 与 1.0 和 HTML5 视频标签

    我正在我的网站中嵌入 HTML5 视频标签 来源是 gstreamer 流 我有一个正在处理 gst 0 10 的管道 gst launch 0 10 v videotestsrc theoraenc oggmux queue tcpser
  • 自定义包装编解码器集成到 Android 中

    我需要开发一个自定义的 包装 视频编解码器并将其集成到 android 中 现在是 JB 稍后是 ICS 我们想要使用 SIM 卡中的一些自定义解密密钥 不要问 最好的方法 允许它与其他非加密媒体一起工作并使用标准媒体播放器或其他 似乎是定
  • jQuery 单击事件仅在 Chrome 中移动鼠标后起作用

    所以我知道有更好的方法来切换风格 但请耐心等待 Chrome 但不是 Firefox 上似乎存在一个小错误 即 单击 事件在事件发生后鼠标移动之前不会执行任何操作 function selectsomething a rel css cli
  • Android Studio 在 macOS Big Sur beta 上崩溃

    更新到 macOS Big 11 0 Beta 20A5395g 的最新 Beta 版本后 Android Studio 4 1 不断关闭 因为 NSOpenGLContext setView must be called from the
  • 如何使用 Ruby 1.9 转换字符编码

    我目前在处理 Amazon API 的结果时遇到问题 该服务返回一个带有 unicode 字符的字符串 在 Mac 上学习 Objective xE2 x80 x93C 学习系列 在 Ruby 1 9 1 中 字符串甚至无法被处理 REXM
  • 预加载背景图片

    有大量关于如何预加载图像的文章 但是我似乎找不到任何关于使用 jquery 预加载背景图像的有用信息 我制作了一个简单的 html 模型来实现我想要实现的目标 http jsfiddle net 3rfhr 出现加载 div 背景已加载 加
  • 无法通过在 web.config 中添加 appcontext 设置来将应用程序设置为使用系统默认 TLS 版本

    根据 net 的指导TLS协议编程 当您的项目面向 net 4 6 时 它建议通过 appcontext 开关配置安全性 当在控制台应用程序的 app config 中添加 appcontext 时 这种方法有效 但是 在网站项目的 web
  • 设置SeekBar的宽度以实现“滑动解锁”效果

    我正在尝试使用 SeekBar 进行滑动解锁功能 我想要的外观如下所示 它由两个图像 一个背景和一个按钮组成 我将背景和 SeekBar 都放在 FrameLayout 中 以便 SeekBar 应该位于背景之上 Like so
  • Google 地图中的灰色区域

    我已经在我的应用程序中 以模式 实现了谷歌地图 但是正如您在下面的图像中看到的那样 有一个我当然想要摆脱的灰色区域 可以移动地图以使灰色区域消失 但这不是必需的 问题是 地图显示在模式框内 其中包含单击用于显示模式的按钮时动态创建的大量内容
  • 重写继承方法时避免显式类型转换

    我有一个基抽象类 它也实现了特定的接口 public interface IMovable
  • 准备弃用 std::iterator

    On March 21st the standards committee voted to approve the deprecation of std iterator proposed in P0174 对于读者来说 一长串的 voi
  • Python 写入文件返回空文件

    我正在尝试执行简单的命令将 hello world 写入文件 Python 2 7 3 default Feb 11 2013 12 48 32 GCC 4 4 6 20120305 Red Hat 4 4 6 4 on linux2 Ty
  • 如何在 Bootstrap 中将 YouTube 嵌入视频居中对齐

    我正在尝试将 YouTube 嵌入视频对齐到引导页面的页面中心 视频的大小始终相同 我的 html 看起来非常简单 div class video div 我尝试了 stackoverflow 中的不同解决方案 它只解决了将 div 居中
  • 运行 concat/uglify 后出现 Angular“状态已定义”错误

    我正在开发一个 AngularJS 应用程序 为了将代码交付到生产环境中 我使用了这个 Grunt 配置 任务 grunt registerTask compile sass compile copy compile assets ngAn
  • 使用 xelatex 进行 Rmarkdown

    我正在尝试使用 Calibri 字体 但据我了解 我首先需要能够使用 xelatex 引擎 这就是我遇到问题的地方 示例代码和错误如下 请注意 我对乳胶很陌生 所以我很可能错过了一些明显的东西 如果重要的话 我安装了 MikTeX 2 9
  • 我可以覆盖 std::hash 吗?

    我可以替换实际的实现std hash用我自己的定义std hash在 C 11 中 我的意思是来自我的代码库 而不触及标准库 在这种情况下 我看不到虚拟函数 多态性有任何用处 所以我想我无论如何都无法改变 std hash 的定义 您可以将
  • 避免 DELETE 查询中的自引用

    我正在尝试删除其名称下不是最新版本的所有记录 但显然您无法引用访问您在同一查询中修改的表 我尝试了这个 但由于上述原因它不起作用 DELETE FROM table WHERE CONCAT name version NOT IN SELE
  • 使用java加密和解密密码使用什么API和算法

    我目前正在使用 Java 创建应用程序 我在 google 上搜索了 java 密码加密 但结果如此巨大 我感到不知所措 如何使用 Java 加密和解密密码 加密和解密密码的最佳实践是什么 我猜 MD5 不是一种可行的方法 因为它是一种单向
  • 如何从包含多个 GzipStream 的文件中读取

    我有一个使用代码创建的文件 如下所示 using var fs File OpenWrite tmp using GZipStream gs new GZipStream fs CompressionMode Compress true u