Frage

None of the similar questions are quite what I'm looking for!

What's wrong with the following code? files is a text array of file contents, and fileNames is the corresponding filename array.

This code always fails at the second-last line with the Save method, but I can't see why the stream would be closed!

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);
}

Thanks for any help - getting desperate here!

This is my solution based on @spender's first comment, although his solution posted below is possibly nicer.

        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;
        }
War es hilfreich?

Lösung

It seems that calling Save is the point when the source streams are read. This means you have to keep them undisposed until after the save. Abandon using statement in this case as it is impossible to extend its scope beyond the loop. Instead, collect your IDisposables and dispose of them once the save is completed.

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();
        }
    }
}

Andere Tipps

@spender answer is spot on but as my 2 cents if you want to be more synonymous with using pattern you can do something like

class

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();
        }

    }
}

How to use

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);

    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top