DotNetZip - 无法访问封闭的Stream

时间:2013-07-11 00:37:28

标签: c# dotnetzip

类似的问题都不是我想要的!

以下代码有什么问题? files是文件内容的文本数组,fileNames是相应的文件名数组。

此代码总是在使用Save方法的倒数第二行失败,但我看不清为什么要关闭该流!

result = new MemoryStream();

using (ZipFile zipFile = new ZipFile())
{
    for (int i = 0; i < files.Count(); i++)
    {
        System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
        Byte[] bytes = encoding.GetBytes(files[i]);
        using (MemoryStream fs = new MemoryStream(bytes))
        {
            zipFile.AddEntry(fileNames[i], fs);
        }
    }
    zipFile.Save(result);
}

感谢您的帮助 - 在这里绝望!

这是我的解决方案,基于@ spender的第一条评论,尽管他在下面发布的解决方案可能更好。

        try
        {
            result = new MemoryStream();
            List<Stream> streams = new List<Stream>();

            if (files.Count > 0)
            {
                using (ZipFile zipFile = new ZipFile())
                {
                    for (int i = 0; i < files.Count(); i++)
                    {

                        System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
                        Byte[] bytes = encoding.GetBytes(files[i]);
                        streams.Add(new MemoryStream(bytes));
                        zipFile.AddEntry(fileNames[i], streams[i]);
                    }
                    zipFile.Save(result);
                }
            }
        }
        catch (Exception ex)
        {
            throw;
        }

2 个答案:

答案 0 :(得分:6)

似乎调用Save是读取源流的点。这意味着在保存之前必须保持它们不被遮挡。在这种情况下放弃using语句,因为无法将其范围扩展到循环之外。相反,收集您的IDisposable并在保存完成后处理它们。

result = new MemoryStream();

using (ZipFile zipFile = new ZipFile())
{
    List<IDisposable> memStreams = new List<IDisposable>();
    try
    {
        for (int i = 0; i < files.Count(); i++)
        {
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            Byte[] bytes = encoding.GetBytes(files[i]);
            MemoryStream fs = new MemoryStream(bytes);
            zipFile.AddEntry(fileNames[i], fs);
            memStreams.Add(fs);
        }
        zipFile.Save(result);
    }
    finally
    {
        foreach(var x in memStreams)
        {
            x.Dispose();
        }
    }
}

答案 1 :(得分:0)

@spender的答案很合适,但如果我想成为使用模式的同义词的话,我的2美分可以作为

public class DisposableBucket : IDisposable
{
    readonly List<IDisposable> listOfDisposables = new List<IDisposable>();

    public TClass Using<TClass>(TClass disposable) where TClass : IDisposable
    {
        listOfDisposables.Add(disposable);
        return disposable;
    }

    public void Dispose()
    {
        foreach (var listOfDisposable in listOfDisposables)
        {
            listOfDisposable.Dispose();
        }

    }
}

使用方法

result = new MemoryStream();
using(var bucket = new DisposableBucket())
{
    using (var zipFile = new ZipFile())
    {
        List<IDisposable> memStreams = new List<IDisposable>();

        for (int i = 0; i < files.Count(); i++)
        {
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            Byte[] bytes = encoding.GetBytes(files[i]);

            var fs = bucket.Using(new MemoryStream(bytes));
            zipFile.AddEntry(fileNames[i], fs);

        }
        zipFile.Save(result);

    }
}