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