Trying to read a MemoryStream into which ZipEntry was extracted

Apr 7, 2011 at 11:41 AM

Hi

One of your example has

using (ZipFile zip = ZipFile.Read(ExistingZipFile))
2{
3 ZipEntry e = zip["MyReport.doc"];
4 e.Extract(OutputStream);


When i use the above example like this
System.IO.MemoryStream s = new System.IO.MemoryStream();
entry.Extract(s);
readfrom(s);

readfrom(system.io.stream from)
{
int got;
while ((got = from.Read(buffer, 0, buffer.Length)) > 0)
{
//////never enters the loop
}
}

The read doesn't succeed. Any help?
Coordinator
Apr 8, 2011 at 3:25 PM

yes - after writing to the stream, but before reading it, you must rewind it.  You need to call s.Seek() to move the stream cursor to the beginning.

in more detail: When you use DotNetZip to extract into a stream, it writes into the stream. This has the side effect of advancing the stream pointer. When the extraction (write) is finished, the pointer in the stream points to EOS - end of stream. If you try reading at that point, there is nothing there.  You need to reset the pointer so that it refers to the beginning of the stream in order to read it.

BUT - I don't know why you would want to extract into a MemoryStream, and then Read from the memorystream.  By using that approach, You've added an additional step that isn't necessary.  You're moving data around more than you need to, which takes longer, and consumes more memory.  To eliminate the extra step, You can simply call ZipEntry.OpenReader() to get a Stream that you can read from directly.  http://cheeso.members.winisp.net/DotNetZipHelp/html/4ef6405c-33ff-a8aa-1731-def3ec5cac24.htm

use it like this:

        using (ZipFile zip = ZipFile.Read(ExistingZipFile))
        {
            ZipEntry e = zip["MyReport.doc"];
            //e.Extract(OutputStream);
            using (Stream s = e.OpenReader())
            {
                int got;
                while ((got = from.Read(buffer, 0, buffer.Length)) > 0) 
                {
                    // buffer contains decompressed data from the entry
                }
            }
        }        

 

May 18, 2012 at 2:23 PM

Hello,

A good reason to reading back a previously extracted memory stream might be to process embedded ZIP files. I wish to list entries from large software distribution ZIP files, themselves containing some ZIP files from which I need to also list the entries (no extraction needed here). 

It seems that the stream provided by OpenReader() does not provide the seek abilities required by ZipFile.Read().

using (ZipFile mainZip = ZipFile.Read(mainZipFilePath))
{
  foreach (ZipEntry zipEntry in mainZip)
  {
    if (zipEntry.IsDirectory || !zipEntry.FileName.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
      continue;
    Console.WriteLine("Processing embedded ZIP file {0}", zipEntry.FileName);
    using (ZipFile embeddedZip = ZipFile.Read(zipEntry.OpenReader()))
    { 
      foreach (ZipEntry embeddedEntry in embeddedZip)
        Console.WriteLine("- embedded ZIP entry found {0}", embeddedEntry.FileName);
    }
  }
}

Unhandled Exception: Ionic.Zip.ZipException: Cannot read that as a ZipFile --->
System.NotSupportedException: Specified method is not supported.
   at Ionic.Crc.CrcCalculatorStream.Seek(Int64 offset, SeekOrigin origin) in CRC32.cs:line 783

Extracting to a memory stream works fine, although I end up extracting tens of megabytes of data.

    Console.WriteLine("Processing embedded ZIP file {0}", zipEntry.FileName);
    System.IO.MemoryStream ms = new System.IO.MemoryStream();
    zipEntry.Extract(ms);
    ms.Seek(0, SeekOrigin.Begin);
    using (ZipFile embeddedZip = ZipFile.Read(ms))
    {
      foreach (ZipEntry embeddedEntry in embeddedZip)
        Console.WriteLine("- embedded ZIP entry found {0}", embeddedEntry.FileName);
    }