4

我正在做一个项目,我需要能够解压缩流和字节数组以及压缩它们。我正在运行一些单元测试,从流中创建 Zip 然后解压缩它们,当我解压缩它们时,DonNetZip 将它们视为 zip 的唯一方法是如果我运行streamToZip.Seek(o,SeekOrigin.Begin)streamToZip.Flush(). 如果我不这样做,我ZipFile.Read(stream).

我想知道是否有人可以解释为什么会这样。我看过几篇关于使用它来实际设置相对读取位置的文章,但没有一篇文章能真正解释为什么在这种情况下需要它。

这是我的代码:

压缩对象:

   public Stream ZipObject(Stream data)
    {
        var output = new MemoryStream();
        using (var zip = new ZipFile())
        {
            zip.AddEntry(Name, data);
            zip.Save(output);
            FlushStream(output);
            ZippedItem = output;
        }

        return output;
    }

解压对象:

 public List<Stream> UnZipObject(Stream data)
    {
        ***FlushStream(data); // This is what I had to add in to make it work***

        using (var zip = ZipFile.Read(data))
        {
            foreach (var item in zip)
            {
                var newStream = new MemoryStream();
                item.Extract(newStream);
                UnZippedItems.Add(newStream);
            }
        }
        return UnZippedItems;
    }

我必须添加的刷新方法:

    private static void FlushStream(Stream stream)
    {
        stream.Seek(0, SeekOrigin.Begin);
        stream.Flush();
    }
4

2 回答 2

8

当您从 中返回outputZipObject,该流已结束- 您刚刚写入了数据。您需要“倒带”它,以便随后可以读取数据。想象一下,您有一个录像带,并且刚刚录制了一个节目 - 您需要在观看之前将其倒带,对吗?这里完全一样。

不过,我建议自己这样做ZipObject——而且我认为没有Flush必要打电话。我也会亲自使用该Position物业:

public Stream ZipObject(Stream data)
{
    var output = new MemoryStream();
    using (var zip = new ZipFile())
    {
        zip.AddEntry(Name, data);
        zip.Save(output);
    }
    output.Position = 0;
    return output;
}
于 2013-09-26T12:29:20.713 回答
3

当您写入流时,位置会更改。如果要解压缩它(相同的流对象),则需要重置位置。否则你会得到一个EndOfStreamException,因为它ZipFile.Read会从stream.Position.

所以

stream.Seek(0, SeekOrigin.Begin); 

或者

stream.Position = 0; 

会成功的。


离题但肯定有用:

public IEnumerable<Stream> UnZipObject(Stream data)
{
    using (var zip = ZipFile.Read(data))
    {
        foreach (var item in zip)
        {
            var newStream = new MemoryStream();
            item.Extract(newStream);
            newStream.Position = 0;
            yield return newStream;
        }
    }
}

不会解压缩内存中的所有项目(因为在 中MemoryStream使用UnZipObject(),仅在迭代时。那是因为提取的项目已产生。(返回一个IEnumerable<Stream>)有关产量的更多信息:http: //msdn.microsoft.com/en-us/库/vstudio/9k7k7cf0.aspx

通常我不会建议将数据作为流返回,因为流类似于迭代器(使用 .Position 作为当前位置)。这样,默认情况下它不是线程安全的。我宁愿将这些内存流返回为ToArray().

于 2013-09-26T12:29:46.227 回答