GZipStream读取超出数据部分的末尾

时间:2015-02-10 19:36:25

标签: c# .net httpwebrequest gzip compression

我的程序通过HttpWebRequest下载一个文件,该文件由几个stringed up gzip压缩文件/部分组成。

因此,当我解压缩responseStream时,GZipStream会在每个文件部分后自行关闭。这不是一个大问题,因为我可以为每个文件创建一个新文件,但问题是:GZipStream读取每个文件,即下一个文件的开头。

这是一个问题,因为我不能将Seek()应用到我的responseStream来返回下一个文件的偏移量,所以下一个文件基本上就丢失了。

对我来说最明显的解决方案是在解压缩之前将NetworkStream复制到MemoryStream中。但我不希望将整个文件加载到内存中,甚至不是文件部分,只需要定义的缓冲区大小(f.e.512kB)。

================== EDITED ====================

我的新解决方案,感谢Tarik

============================================

下载流程:

  using (DownloadStream dlStream = new DownloadStream(responseStream, file.compressedSize))
  using (GZipStream zip = new GZipStream(dlStream, CompressionMode.Decompress, true))
  {
       await zip.CopyToAsync(fs);
  }

DownloadStream类:

class DownloadStream : Stream
{
    Stream strm;
    int len;
    int pos;

    public DownloadStream(Stream netStream, int fileSize)
    {
        strm = netStream;
        len = fileSize;
        pos = 0;
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        int rest = len - pos;
        int nRead;

        if (count > rest)
        {
            nRead = strm.Read(buffer, 0, rest);
        }
        else
        {
            nRead = strm.Read(buffer, 0, count);
        }
        pos += nRead;

        return nRead;
    }

    public override bool CanRead
    {
        get
        {
            return true;
        }
    }

//...add all other must-overrideables throwing NotImplementedException.

}

这就是我所需要的全部。可以看出,它还支持异步解压缩任务,几乎不使用任何内存。 非常感谢这个简单的解决方案Tarik! :)

1 个答案:

答案 0 :(得分:0)

我会创建一个实现流的类。我会在指示EOF之前将响应流及其应读取的数据大小传递给此类构造函数。在内部,此流将从底层响应流中读取,并在达到指定限制时停止读取。 我会一次一个地设置这些流类,并将它们传递给GZipStream。