2015-02-10 39 views
0

我的程序通过HttpWebRequest下载一个文件,其中包含几个经过压缩的gzip压缩文件/部分。GZipStream超出我的数据部分末尾

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

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

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

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

我的新解决方案,谢谢塔里克

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

下载Process:

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. 

} 

这就是我所需要的。正如人们所看到的,它也支持异步解压缩任务,并且几乎不使用内存。 非常感谢你这个简单的解决方案塔里克! :)

+0

你能预先确定每个压缩文件的大小吗? – Tarik 2015-02-10 19:43:53

+0

当然,当您查看代码时,会有file.compressedSize。此外,我还保存了流内文件部分的所有偏移量/查找点以及未压缩的大小。 – Showdown 2015-02-10 19:48:01

回答

0

我会创建一个实现流的类。我会传递给这个类的构造函数responsestream和它在指示EOF之前应该读取的数据的大小。在内部,该流将从底层响应流读取,并在达到指定限制时停止读取。 我会用所需的大小一次一个实例化这些流类,并将它们传递给GZipStream。