[
  {
    "Id": "163160",
    "ThreadId": "48865",
    "Html": "Hi guys,<br>\r\n<br>\r\nThis library seems to do pretty much what I need but I'm wondering if the next thing is possible with it:<br>\r\n<br>\r\nI have a hundred files in my database which I would like to stream into a zip file. But in the remarks I read that if I would like to add a file as a stream, my stream must remained open until the save method is called. This means I need to open 100 simultanious connections to my database for just one request actually. Not only my connection pool is drained out, but I'm getting table locks instead of row locks eventually.<br>\r\n<br>\r\nIs it possible to stream contents to the zipfile immediately, without waiting for the Save method being called? Cause than I can do with just one connection. <br>\r\n<br>\r\nCheers,<br>\r\nWes<br>\r\n<br>\r\nJust to let you know: I have it working in this way with CSharpZipLib but I would like to have it ported to use the DotNetZip Lib because of the GPL license. Below is the sample of how I do this right now. As you can see I open a binarystream, write the contents to the ZipOutPutStream right away and the binarystream is closed directly.<br>\r\n<code>\r\n<pre>/// &lt;summary&gt;\r\n/// Adds the SPFile to the zip output stream.\r\n/// &lt;/summary&gt;\r\n/// &lt;param name=&quot;zipOutputStream&quot;&gt;The zip output stream.&lt;/param&gt;\r\n/// &lt;param name=&quot;file&quot;&gt;The file.&lt;/param&gt;\r\n/// &lt;param name=&quot;path&quot;&gt;The path.&lt;/param&gt;\r\npublic static void AddSPFile(this ZipOutputStream zipOutputStream, SPFile file, string path) {\r\n    string filePath = Path.Combine(path, file.Name);\r\n\r\n    ZipEntry entry = new ZipEntry(filePath);\r\n    entry.DateTime = file.TimeCreated;\r\n    zipOutputStream.PutNextEntry(entry);\r\n\r\n    using (Stream fileStream = file.OpenBinaryStream()) {\r\n        byte[] buffer = new byte[4096];\r\n        int sourceBytes;\r\n        do {\r\n            sourceBytes = fileStream.Read(buffer, 0, buffer.Length);\r\n            zipOutputStream.Write(buffer, 0, sourceBytes);\r\n        } while (sourceBytes &gt; 0);\r\n    }\r\n}\r\n</pre>\r\n</code>\r\n",
    "PostedDate": "2009-03-01T03:35:50.89-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "163193",
    "ThreadId": "48865",
    "Html": "<p>Webbes, </p>\r\n<p>I understand your situation.  I have to think about it a little.  Just at the outset, I have a couple ideas.</p>\r\n<p>You CAN stream the contents of the zip entry immediately, as soon as you add the entry.  To do this, you would call Save() immediately after adding each file or stream.    This would cause the current stream being added to be read from the database, and then written to the zip archive on disk.  On subsequent calls to Save(), the same thing happens with the current entry, but the data for the previously-written entries is just transferred from one zip file to another.  This seems like it would work, avoiding the 100 simultaneous connections to the database, though of course, each file saved to the zip gets written and rewritten, (n-i) times.  The first one, 100 times. The second entry 99 times, etc.   Seems very inefficient.  But it would avoid the simultaneous db connections problem.<br>\r\n<br>\r\nA real solution to your problem would eliminate the simultaneous db connections while at the same time not produce any redundant data writes. <br>\r\nThere are a couple ways I could address this. </p>\r\n<ul>\r\n    <li>Key off the entry events, Saving_BeforeWriteEntry and Saving_AfterWriteEntry.   An app could register a progress handler, and when it receives this event, which includes the name of the entry about to be written, the app could then open the stream for that particular entry and hand it to the library.  Then, in the After event, the app could close the stream for that entry.  Currently, this WON'T REALLY WORK, because the event model does not allow the app to communicate back to the library a stream for the ZipEntry to be saved to the archive.  But it wouldn't be hard to introduce this new capability. </li>\r\n    <li>Take the approach you suggest:  write the data immediately.  This would be a higher-impact change, and it would take much longer to write and test, because it changes the model for how the ZipFile class works internally.   I see what you mean - it could be very convenient for your use case; but given the design of ZipFile right now, it would be harder to do. </li>\r\n</ul>\r\n<p>There may be other ways, too. <br>\r\n<br>\r\nWhat do you think of the first option? </p>\r\n",
    "PostedDate": "2009-03-01T08:17:23.11-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "163194",
    "ThreadId": "48865",
    "Html": "This discussion has been copied to a work item. Click <a href=\"http://dotnetzip.codeplex.com/WorkItem/View.aspx?WorkItemId=7192\">here</a> to go to the work item and continue the discussion.",
    "PostedDate": "2009-03-01T08:18:29.967-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "163199",
    "ThreadId": "48865",
    "Html": "<p>The solution with events would work and I see you've created a workitem for it. Maybe I'll see if i can do something with it myself.</p>\r\n<p>The first option is not really an option. I can't create 100 zipfiles before I send one. It would be to resource intensive. My solution works in a SharePoint enterprise portal and must be very well performing.</p>\r\n<p>Cheers,</p>\r\n<p>Wes</p>\r\n",
    "PostedDate": "2009-03-01T08:46:54.19-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "163218",
    "ThreadId": "48865",
    "Html": "ok, makes sense.  Well, have a look at the event code. <br>\r\nI haven't looked to see if this would work, but I am thinking: <br>\r\n<ul>\r\n    <li>add a Stream param to the ProgressEventArgs type </li>\r\n    <li>in your own progress event handler, open the stream and set the stream param in the EventArgs type </li>\r\n    <li>check the stream in the ZipFile class upon completion of the Saving_BeforeSaveEntry event </li>\r\n    <li>if the stream is non-null, then copy that value to the ZipEntry._sourceStream private/internal member. (It needs to be marked internal for this to work, not sure if it already is)</li>\r\n    <li>then, in ZipEntry.Write(), the logic already uses the _sourceStream </li>\r\n    <li>also in your application code, close the stream.  </li>\r\n</ul>\r\n<p>I think there would be some loose ends to clean up, but that would be the basic idea.</p>\r\n",
    "PostedDate": "2009-03-01T09:48:29.647-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "163742",
    "ThreadId": "48865",
    "Html": "<span style=\"font-size:13px\">\r\n<p>&nbsp;</p>\r\n</span>\r\n<p><span style=\"font-size:13px;color:#0000ff\"><span style=\"font-size:13px;color:#0000ff\">I tried the reverse: delay opening the file like in <br>\r\n<span style=\"font-size:13px;color:#0000ff\">\r\n<p>&nbsp;</p>\r\n</span><span style=\"font-size:13px\">\r\n<p>zip.AddFileStream(fileName, </p>\r\n</span>\r\n<p><span style=\"font-size:13px;color:#0000ff\">string</span><span style=\"font-size:13px\">.Empty, </span><span style=\"font-size:13px;color:#0000ff\">new</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#2b91af\">LazyStream</span><span style=\"font-size:13px\">(() =&gt; catalog.Open(fileName)));<br>\r\n<br>\r\nI expected the Save method to close the file, but it is not the case and now I can't close it because I have no Stream property on the ZipEntry<br>\r\n<br>\r\n</span>with the following LazyStream class (the delegate is the same as Func&lt;Stream&gt; but can be used with .net 2.0)<br>\r\n<br>\r\n<br>\r\npublic</p>\r\n</span>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">delegate</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#2b91af\">Stream</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#2b91af\">StreamOpener</span><span style=\"font-size:13px\">();\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">public</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">class</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#2b91af\">LazyStream</span><span style=\"font-size:13px\"> : </span><span style=\"font-size:13px;color:#2b91af\">Stream\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<span style=\"font-size:13px\">\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span>\r\n<p><span style=\"font-size:13px;color:#0000ff\">private</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#2b91af\">StreamOpener</span><span style=\"font-size:13px\"> Opener;\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">private</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#2b91af\">Stream</span><span style=\"font-size:13px\"> BaseStream;\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">public</span><span style=\"font-size:13px\"> LazyStream(</span><span style=\"font-size:13px;color:#2b91af\">StreamOpener</span><span style=\"font-size:13px\"> opener)\r\n<p>&nbsp;</p>\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">if</span><span style=\"font-size:13px\"> (opener == </span><span style=\"font-size:13px;color:#0000ff\">null</span><span style=\"font-size:13px\">)\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">throw</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">new</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#2b91af\">ArgumentNullException</span><span style=\"font-size:13px\">();\r\n<p>&nbsp;</p>\r\n<p>Opener = opener;</p>\r\n<p>}</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">public</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">override</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">bool</span><span style=\"font-size:13px\"> CanRead\r\n<p>&nbsp;</p>\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">get</span><span style=\"font-size:13px\"> { </span><span style=\"font-size:13px;color:#0000ff\">return</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">true</span><span style=\"font-size:13px\">; }\r\n<p>&nbsp;</p>\r\n<p>}</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">public</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">override</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">bool</span><span style=\"font-size:13px\"> CanSeek\r\n<p>&nbsp;</p>\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">get</span><span style=\"font-size:13px\"> { </span><span style=\"font-size:13px;color:#0000ff\">return</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">true</span><span style=\"font-size:13px\">; }\r\n<p>&nbsp;</p>\r\n<p>}</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">public</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">override</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">bool</span><span style=\"font-size:13px\"> CanWrite\r\n<p>&nbsp;</p>\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">get</span><span style=\"font-size:13px\"> { </span><span style=\"font-size:13px;color:#0000ff\">return</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">false</span><span style=\"font-size:13px\">; }\r\n<p>&nbsp;</p>\r\n<p>}</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">public</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">override</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">void</span><span style=\"font-size:13px\"> Flush()\r\n<p>&nbsp;</p>\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">throw</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">new</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#2b91af\">NotImplementedException</span><span style=\"font-size:13px\">();\r\n<p>&nbsp;</p>\r\n<p>}</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">public</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">override</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">long</span><span style=\"font-size:13px\"> Length\r\n<p>&nbsp;</p>\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">get\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<span style=\"font-size:13px\">\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span>\r\n<p><span style=\"font-size:13px;color:#0000ff\">if</span><span style=\"font-size:13px\"> (BaseStream == </span><span style=\"font-size:13px;color:#0000ff\">null</span><span style=\"font-size:13px\">)\r\n<p>&nbsp;</p>\r\n<p>BaseStream = Opener();</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">return</span><span style=\"font-size:13px\"> BaseStream.Length;\r\n<p>&nbsp;</p>\r\n<p>}</p>\r\n<p>}</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">public</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">override</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">long</span><span style=\"font-size:13px\"> Position\r\n<p>&nbsp;</p>\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">get\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<span style=\"font-size:13px\">\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span>\r\n<p><span style=\"font-size:13px;color:#0000ff\">if</span><span style=\"font-size:13px\"> (BaseStream == </span><span style=\"font-size:13px;color:#0000ff\">null</span><span style=\"font-size:13px\">)\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">return</span><span style=\"font-size:13px\"> 0;\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">return</span><span style=\"font-size:13px\"> BaseStream.Position;\r\n<p>&nbsp;</p>\r\n<p>}</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">set\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<span style=\"font-size:13px\">\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span>\r\n<p><span style=\"font-size:13px;color:#0000ff\">if</span><span style=\"font-size:13px\"> (</span><span style=\"font-size:13px;color:#0000ff\">value</span><span style=\"font-size:13px\"> != 0)\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">throw</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">new</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#2b91af\">ArgumentOutOfRangeException</span><span style=\"font-size:13px\">();\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">if</span><span style=\"font-size:13px\"> (BaseStream != </span><span style=\"font-size:13px;color:#0000ff\">null</span><span style=\"font-size:13px\"> &amp;&amp; BaseStream.Position != 0)\r\n<p>&nbsp;</p>\r\n<p>{</p>\r\n<p>BaseStream.Close();</p>\r\n<p>BaseStream = </p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">null</span><span style=\"font-size:13px\">;\r\n<p>&nbsp;</p>\r\n<p>}</p>\r\n<p>}</p>\r\n<p>}</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">public</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">override</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">int</span><span style=\"font-size:13px\"> Read(</span><span style=\"font-size:13px;color:#0000ff\">byte</span><span style=\"font-size:13px\">[] buffer, </span><span style=\"font-size:13px;color:#0000ff\">int</span><span style=\"font-size:13px\"> offset, </span><span style=\"font-size:13px;color:#0000ff\">int</span><span style=\"font-size:13px\"> count)\r\n<p>&nbsp;</p>\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">if</span><span style=\"font-size:13px\"> (BaseStream == </span><span style=\"font-size:13px;color:#0000ff\">null</span><span style=\"font-size:13px\">)\r\n<p>&nbsp;</p>\r\n<p>BaseStream = Opener();</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">if</span><span style=\"font-size:13px\"> (!BaseStream.CanRead)\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">throw</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">new</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#2b91af\">InvalidOperationException</span><span style=\"font-size:13px\">();\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">int</span><span style=\"font-size:13px\"> n = 0;\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">int</span><span style=\"font-size:13px\"> m;\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">while</span><span style=\"font-size:13px\"> (count != 0 &amp;&amp; (m = BaseStream.Read(buffer, offset, count)) != 0)\r\n<p>&nbsp;</p>\r\n<p>{</p>\r\n<p>offset += m;</p>\r\n<p>n += m;</p>\r\n<p>count -= m;</p>\r\n<p>}</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">return</span><span style=\"font-size:13px\"> n;\r\n<p>&nbsp;</p>\r\n<p>}</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">public</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">override</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">long</span><span style=\"font-size:13px\"> Seek(</span><span style=\"font-size:13px;color:#0000ff\">long</span><span style=\"font-size:13px\"> offset, </span><span style=\"font-size:13px;color:#2b91af\">SeekOrigin</span><span style=\"font-size:13px\"> origin)\r\n<p>&nbsp;</p>\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">if</span><span style=\"font-size:13px\"> (origin == </span><span style=\"font-size:13px;color:#2b91af\">SeekOrigin</span><span style=\"font-size:13px\">.Current)\r\n<p>&nbsp;</p>\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">if</span><span style=\"font-size:13px\"> (offset != 0)\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">throw</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">new</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#2b91af\">ArgumentOutOfRangeException</span><span style=\"font-size:13px\">();\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">if</span><span style=\"font-size:13px\"> (BaseStream == </span><span style=\"font-size:13px;color:#0000ff\">null</span><span style=\"font-size:13px\">)\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">return</span><span style=\"font-size:13px\"> 0;\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">return</span><span style=\"font-size:13px\"> BaseStream.Position;\r\n<p>&nbsp;</p>\r\n<p>}</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">if</span><span style=\"font-size:13px\"> (origin != </span><span style=\"font-size:13px;color:#2b91af\">SeekOrigin</span><span style=\"font-size:13px\">.Begin)\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">throw</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">new</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#2b91af\">ArgumentOutOfRangeException</span><span style=\"font-size:13px\">();\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">if</span><span style=\"font-size:13px\"> (offset != 0)\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">throw</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">new</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#2b91af\">ArgumentOutOfRangeException</span><span style=\"font-size:13px\">();\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">if</span><span style=\"font-size:13px\"> (BaseStream != </span><span style=\"font-size:13px;color:#0000ff\">null</span><span style=\"font-size:13px\">)\r\n<p>&nbsp;</p>\r\n<p>BaseStream.Close();</p>\r\n<p>BaseStream = </p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">null</span><span style=\"font-size:13px\">;\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">return</span><span style=\"font-size:13px\"> 0;\r\n<p>&nbsp;</p>\r\n<p>}</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">public</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">override</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">void</span><span style=\"font-size:13px\"> SetLength(</span><span style=\"font-size:13px;color:#0000ff\">long</span><span style=\"font-size:13px\"> value)\r\n<p>&nbsp;</p>\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">throw</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">new</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#2b91af\">NotImplementedException</span><span style=\"font-size:13px\">();\r\n<p>&nbsp;</p>\r\n<p>}</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">public</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">override</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">void</span><span style=\"font-size:13px\"> Write(</span><span style=\"font-size:13px;color:#0000ff\">byte</span><span style=\"font-size:13px\">[] buffer, </span><span style=\"font-size:13px;color:#0000ff\">int</span><span style=\"font-size:13px\"> offset, </span><span style=\"font-size:13px;color:#0000ff\">int</span><span style=\"font-size:13px\"> count)\r\n<p>&nbsp;</p>\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">throw</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">new</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#2b91af\">NotImplementedException</span><span style=\"font-size:13px\">();\r\n<p>&nbsp;</p>\r\n<p>}</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">public</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">override</span><span style=\"font-size:13px\"> </span><span style=\"font-size:13px;color:#0000ff\">void</span><span style=\"font-size:13px\"> Close()\r\n<p>&nbsp;</p>\r\n<p>{</p>\r\n<p>&nbsp;</p>\r\n</span></p>\r\n<p><span style=\"font-size:13px;color:#0000ff\">if</span><span style=\"font-size:13px\"> (BaseStream != </span><span style=\"font-size:13px;color:#0000ff\">null</span><span style=\"font-size:13px\">)\r\n<p>&nbsp;</p>\r\n<p>BaseStream.Close();</p>\r\n<p>}</p>\r\n<p>}</p>\r\n</span></p>\r\n",
    "PostedDate": "2009-03-03T01:34:56.62-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "163863",
    "ThreadId": "48865",
    "Html": "<p>Hmm, interesting. <br>\r\nBut yes, DotNetZip does not close streams that are presented to it from external sources. </p>\r\n<p>I have to think about this some more. </p>\r\n",
    "PostedDate": "2009-03-03T06:44:20.4-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "164490",
    "ThreadId": "48865",
    "Html": "<p>Hey Webbes, <br>\r\nI thought about this some more and came up with this idea. It introduces a new interface into DotNetZip - IStreamDispenser - which exposes just two methods:  Open and Return.   DotNetZip calls the Open method when it needs a stream and calls the Return when it is done.  <br>\r\nYou use it this way: </p>\r\n<pre><span style=\"color:#228b22\">void</span> <span style=\"color:#5f9ea0\">IStreamDispenser</span>.<span style=\"color:#b8860b\">Return</span>(<span style=\"color:#5f9ea0\">System</span>.<span style=\"color:#5f9ea0\">IO</span>.<span style=\"color:#228b22\">Stream</span> <span style=\"color:#b8860b\">s</span>, <span style=\"color:#228b22\">string</span> <span style=\"color:#b8860b\">name</span>)\r\n{\r\n    <span style=\"color:#5f9ea0\">Console</span>.WriteLine(<span style=\"color:#bc8f8f\">&quot;closing {0}&quot;</span>, name);\r\n    <span style=\"color:#5f9ea0\">s</span>.Close();\r\n}\r\n\r\n\r\n<span style=\"color:#5f9ea0\">System</span>.<span style=\"color:#5f9ea0\">IO</span>.<span style=\"color:#228b22\">Stream</span> <span style=\"color:#5f9ea0\">IStreamDispenser</span>.<span style=\"color:#b8860b\">Open</span>(<span style=\"color:#228b22\">string</span> <span style=\"color:#b8860b\">name</span>)\r\n{\r\n    <span style=\"color:#5f9ea0\">Console</span>.WriteLine(<span style=\"color:#bc8f8f\">&quot;opening {0}&quot;</span>, name);\r\n    <span style=\"color:#5f9ea0\">System</span>.<span style=\"color:#5f9ea0\">IO</span>.<span style=\"color:#228b22\">Stream</span> <span style=\"color:#b8860b\">s</span> = <span style=\"color:#5f9ea0\">System</span>.<span style=\"color:#5f9ea0\">IO</span>.<span style=\"color:#5f9ea0\">File</span>.OpenRead(<span style=\"color:#5f9ea0\">System</span>.<span style=\"color:#5f9ea0\">IO</span>.<span style=\"color:#5f9ea0\">Path</span>.Combine(<span style=\"color:#bc8f8f\">&quot;fodder&quot;</span>,name));\r\n    <span style=\"color:#a020f0\">return</span> s;\r\n}\r\n\r\n\r\n<span style=\"color:#a020f0\">public</span> <span style=\"color:#228b22\">void</span> <span style=\"color:#b8860b\">Run</span>()\r\n{\r\n    <span style=\"color:#a020f0\">using</span> (<span style=\"color:#228b22\">ZipFile</span> <span style=\"color:#b8860b\">zip</span> = <span style=\"color:#a020f0\">new</span> ZipFile())\r\n    {\r\n\t<span style=\"color:#a020f0\">foreach</span> (<span style=\"color:#228b22\">var</span> <span style=\"color:#b8860b\">f</span> <span style=\"color:#a020f0\">in</span> <span style=\"color:#5f9ea0\">System</span>.<span style=\"color:#5f9ea0\">IO</span>.<span style=\"color:#5f9ea0\">Directory</span>.GetFiles(DirectoryToZip))\r\n\t    <span style=\"color:#5f9ea0\">zip</span>.AddFileStream(f, <span style=\"color:#bc8f8f\">&quot;&quot;</span>, <span style=\"color:#5f9ea0\">null</span>);\r\n\t<span style=\"color:#5f9ea0\">zip</span>.StreamDispenser = <span style=\"color:#a020f0\">this</span>;\r\n\t<span style=\"color:#5f9ea0\">zip</span>.Save(ZipArchiveName);\r\n    }\r\n}\r\n</pre>\r\n<p>The StreamDispenser methods are called once for each entry, and only within the scope of the ZipFile.Save(), and only when the stream you have passed origially is null.  <br>\r\n<br>\r\nCouple questions:</p>\r\n<ol>\r\n    <li>Would this work for you? </li>\r\n    <li>Can you see a simpler or more elegeant way to do this?  \r\n    <ol type=a>\r\n        <li>One option is to replace the interface with a simple delegate [ Stream GetStream(string name) ];  again it gets called just-in-time (when saving) when the input stream is null.  Then I'd modify DotNetZip to automatically call Close() and Dispose() on the stream within when it is finished writing that entry.  I don't like this option so much because in some cases the stream to be read is a single stream that contains multiple entries, and the application just seeks around to get to the right spot.  Closing that stream would be the wrong thing.   [Actually - not sure this is a valid concern.  If necessary the app could wrap the original stream with a shim that does nothing on Close()]</li>\r\n        <li>Another option is to use a delegate as above, but also add a bool property &quot;AutoClose&quot; to make the Close/Dispose behavior optional and explicit.  </li>\r\n    </ol>\r\n    </li>\r\n</ol>\r\n<p>If you want to try out the StreamDispenser, grab v1.8.1.9 . <br>\r\nAnd I'm interested in your comments on the design.</p>\r\n",
    "PostedDate": "2009-03-04T12:17:42.37-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "164709",
    "ThreadId": "48865",
    "Html": "<p>This could definately work for me, and I'm happy with this option already.</p>\r\n<p>I would prefer events though. I would create something like this (if I had the time to really get into the library. I don't know if I can really access the underlying Stream of a ZipEntry for example) :</p>\r\n<p>Additions to the zip class:</p>\r\n<code>\r\n<pre>public event EventHandler&lt;StreamSavingEventArgs&gt; SavingStream;\r\npublic event EventHandler&lt;StreamSavingEventArgs&gt; SavedStream;\r\n\r\nprotected virtual void OnSavingStream(StreamSavingEventArgs eventArgs){\r\n   EventHandler&lt;StreamSavingEventArgs&gt; temp = SavingStream;\r\n   if(temp != null){\r\n      temp(this, eventArgs);\r\n   }\r\n}\r\n\r\nprotected virtual void OnSavedStream(StreamSavingEventArgs eventArgs){\r\n   EventHandler&lt;StreamSavingEventArgs&gt; temp = SavedStream;\r\n   if(temp != null){\r\n      temp(this, eventArgs);\r\n   }\r\n}\r\n\r\n//I imagine there's something like a SaveStream method\r\nprivate void SaveStream(ZipEntry zipEntry){\r\n   StreamSavingEventArgs eventArgs = new StreamSavingEventArgs(zipEntry);\r\n   OnSavingStream(eventArgs);\r\n   \r\n   //all other code that actually writes steam goes in here\r\n\r\n   //note: reuse the eventargs so I can access my State object again\r\n   OnSavedStream(eventArgs);\r\n}\r\n</pre>\r\n</code>\r\n<p>One extra class:</p>\r\n<code>\r\n<pre>public class StreamSavingEventArgs : EventArgs {\r\n   public StreamSavingEventArgs (ZipEntry zipEntry) {\r\n       this.ZipEntry = zipEntry;\r\n   }\r\n\r\n   public object State { get; set; }\r\n\r\n   public ZipEntry ZipEntry { get; private set; }\r\n}\r\n</pre>\r\n</code>\r\n<p>With this I could do whatever I want:</p>\r\n<ul>\r\n    <li>I could use only the SavingStream to open a stream: </li>\r\n    <li>I could use only the SavedStream to close a stream: </li>\r\n    <li>I could use the combination of them to open a stream on the beginning, add some object to the State property of my StreamSavingEventArgs, and then close the stream. </li>\r\n</ul>\r\n<code>\r\n<pre>public void Run()\r\n{\r\n    using (ZipFile zip = new ZipFile())\r\n    {\r\n\t//add streams here\r\n\tzip.SavedStream += (o,e)=&gt;e.ZipEntry.Stream.Dispose();\r\n\tzip.Save(ZipArchiveName);\r\n    }\r\n}\r\n</pre>\r\n</code>\r\n<p>The State property is optional but I can imagine a use where people would like to have an object in the end that they've created in the beginning.</p>\r\n<p>You could even make it more generic by creating SavingEntry and SavedEntry events that get called for each ZipEntry that's about to get saved or has just been saved. An enumerator could be used to check the type of entry.</p>\r\n<code>\r\n<pre>public void Run()\r\n{\r\n    using (ZipFile zip = new ZipFile())\r\n    {\r\n\t//add streams here\r\n\tzip.SavedEntry += (o,e)=&gt;{if(e.ZipEntry.EntryType == ZipEntryType.Stream){e.ZipEntry.Stream.Dispose();}}\r\n\tzip.Save(ZipArchiveName);\r\n    }\r\n}\r\n</pre>\r\n</code>\r\n<p>That would probably be my choice. I don't know the library that well though and I don't know if it's hard to implement so I'm happy with your solution as is already.</p>\r\n<p>Thanks,</p>\r\n<p>Wes</p>\r\n",
    "PostedDate": "2009-03-05T01:54:45.847-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "164760",
    "ThreadId": "48865",
    "Html": "I would prefer something with delegates or events, but not an interface: using anonymous methods or lambdas is so easy.\r\n",
    "PostedDate": "2009-03-05T04:25:15.467-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "164875",
    "ThreadId": "48865",
    "Html": "<p>Hey, thanks for the input. <br>\r\nyou know, I was halfway to implementing this feature with a matched pair of delegates, when I changed course and went to an interface. I had read something that said delegates are sort of an interface with a single method.  And it felt not quite right to introduce 2 new delegates for this one new feature. <br>\r\nBut I can see your point. </p>\r\n<p>There already is a SaveProgress event, and there's an emum that describes the &quot;save state&quot;.  Two of the states are: BeforeWriteEntry  and AfterWriteEntry.  These are the points in time when the library would need a stream to be opened and closed.  At first I was thinking I could stuff this capability into that SaveProgress event, and even re-use those save states....but that didn't feel right either.  Overloading the progress event to enable opening and closing streams... it felt like I was hiding the feature.  </p>\r\n<p>I could do this with a <em>single </em>new event and a new EventArgs type.  Maybe call it StreamDispenserEventArgs.  The point with that name is to distinguish it from the SaveProgressEventArgs that already exits.  (SavingStreamEventArgs feels to similar).   In the EventArgs type I could insert an enum that tells the app if the library is requesting a stream be opened, or closed (or whatever).  And this event would be called not for every entry, but only for the entries with null (unspecified) streams.   What do you think of that?<br>\r\n<br>\r\nor do you really want two distinct events here? <br>\r\n<br>\r\nNone of this is hard to implement in any case - the external interface is what we're talking about, and the internal mechanics are already there. </p>\r\n<p> </p>\r\n",
    "PostedDate": "2009-03-05T08:08:58.887-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "164928",
    "ThreadId": "48865",
    "Html": "Cheeso,<br>\r\n<br>\r\nI would really go for the way I described above with the two events. Simply because it's according to all framework design guidelines and gives me full flexibility.<br>\r\n<br>\r\nTmho every class that ends with EventArgs looks like other classes that end with EventArgs. But it's a design guideline which helps me a lot in finding the correct eventargs for my events and in explaining what they should be used for.<br>\r\n<br>\r\nSame goes with the TWO events instead of one. It's simply a mather of design guidelines which I'm pretty happy with. It's symetric code and makes sense to most developers right away. As soon I find an event called 'Verbing' I know there might be an event called 'Verbed'. I know that the first one will be triggered on the start of the action and the latter when it's finished.<br>\r\n<br>\r\nBut again I'm happy with everything you provide. These opinions of mine are definately not sacred.<br>\r\n<br>\r\nCheers,<br>\r\n<br>\r\nWesley<br>\r\n",
    "PostedDate": "2009-03-05T09:24:46.607-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "164943",
    "ThreadId": "48865",
    "Html": "<p>Wesley, what you say makes sense. <br>\r\njust one more thing - <br>\r\nthe name of the events.  I get the rationale behind Verbing and Verbed. You proposed SavingStream and SavedStream, which makes sense to me if it is a geenral purpose event </p>\r\n<p>But there is already a SaveProgress event, in which there is a BeforeSaveEntry and AfterSaveEntry.  That event is a general purpose notification event. </p>\r\n<p>OTOH, There's a distinct and more specific purpose for this pair of events we're discussing - to obtain and later dispose streams on a just-in-time basis. And I'm suggesting that the name should more clearly communicate that specific purpose. Also, to go along with that I'm suggesting that the operation and behavior also reflect the purpose - these events would be called only when needing a stream to be opened just-in-time, rather than being called for every entry being saved.  In other words it's not really &quot;SavingStream&quot;, it's &quot;ObtainStream&quot;.   We already have a something equivalent to SavingStream - it is in the SaveProgress event. By the same token, it's not really &quot;SavedStream&quot;, it's &quot;AllDoneWithYourStream&quot;. </p>\r\n<p>What do you think?</p>\r\n<p>Those are not the right names, but maybe you get my point: Saving and Saved seem not quite right. </p>\r\n",
    "PostedDate": "2009-03-05T09:45:04.017-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "164949",
    "ThreadId": "48865",
    "Html": "As soon as I wrote that I considered another usage scenario, from another thread on this forum, where the application was removing the file-to-be-zipped before it was completely zipped up.  <br>\r\nSo now I'm thinking that an additional pair of general purpose events, as you suggest, SavingStream and SavedStream, might be the right idea.  This would work for your scenario - where the app provides a stream just for as long as the library needs it - and it would also work for the other scenario, too, where someone wants to remove a file.<br>\r\n <br>\r\nok, that raises a new question - why not just overload the SaveProgress event with this?  If it is general purpose, then there are already events firing at those moments, which could be used for this purpose. This was my original idea, which I then moved away from because it felt incorrect to overload the SaveProgress event with the new capability.  <br>\r\n<br>\r\n",
    "PostedDate": "2009-03-05T09:51:16.737-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "164978",
    "ThreadId": "48865",
    "Html": "<p>While browsing a little bit though the help file it's all getting a little bit clearer for me. Actually the functionally is in there allready IF the stream property of a ZipEntry could be reached.</p>\r\n<code>\r\n<pre>public static void SaveProgress(object sender, SaveProgressEventArgs e)\r\n{\r\n    if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry)\r\n    {\r\n        e.CurrentEntry.Stream = //Open your stream;\r\n    }\r\n    else if (e.EventType == ZipProgressEventType.Saving_AfterSaveEntry)\r\n    {\r\n       e.CurrentEntry.Stream.Dispose();\r\n    }\r\n}\r\n\r\n</pre>\r\n</code>\r\n<p>So maybe all you need to do is to make stream a reachable property.</p>\r\n<p>Cheers,</p>\r\n<p>Wes</p>\r\n",
    "PostedDate": "2009-03-05T10:39:05.217-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "165011",
    "ThreadId": "48865",
    "Html": "<p>yes, <em>exactly</em>. <br>\r\nAnd by your making the suggestion, I am guessing you feel that such an extension does not overly complexify the SaveProgress event?  </p>\r\n<p>&nbsp;</p>\r\n",
    "PostedDate": "2009-03-05T11:58:30.777-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "165047",
    "ThreadId": "48865",
    "Html": "No, I could definately work with this. It's just that I didn't expect the ZipEntry to be accessible from the progress event...\r\n",
    "PostedDate": "2009-03-05T14:10:38.917-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "165053",
    "ThreadId": "48865",
    "Html": "ok, give me a moment to run some tests and I will post the updated library with this change. \r\n",
    "PostedDate": "2009-03-05T14:16:01.03-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "165075",
    "ThreadId": "48865",
    "Html": "<p>Ok, the v1.8.1.11 library has the update where you can set the stream just-in-time. <br>\r\nTo use it you will code a SaveProgress event like so: </p>\r\n<pre>        <span style=\"color:#a020f0\">public</span> <span style=\"color:#a020f0\">static</span> <span style=\"color:#228b22\">void</span> <span style=\"color:#0000ff\">SaveProgress</span>(<span style=\"color:#228b22\">object</span> <span style=\"color:#b8860b\">sender</span>, <span style=\"color:#228b22\">SaveProgressEventArgs</span> <span style=\"color:#b8860b\">e</span>)\r\n        {\r\n            <span style=\"color:#a020f0\">if</span> (<span style=\"color:#5f9ea0\">e</span>.EventType == <span style=\"color:#5f9ea0\">ZipProgressEventType</span>.Saving_BeforeWriteEntry)\r\n            {\r\n                <span style=\"color:#a020f0\">if</span> (<span style=\"color:#5f9ea0\">e</span>.<span style=\"color:#5f9ea0\">CurrentEntry</span>.Source == <span style=\"color:#5f9ea0\">Ionic</span>.<span style=\"color:#5f9ea0\">Zip</span>.<span style=\"color:#5f9ea0\">ZipEntry</span>.<span style=\"color:#5f9ea0\">EntrySource</span>.Stream &amp;&amp;\r\n                    <span style=\"color:#5f9ea0\">e</span>.<span style=\"color:#5f9ea0\">CurrentEntry</span>.InputStream == <span style=\"color:#5f9ea0\">null</span>)\r\n                {\r\n                    <span style=\"color:#5f9ea0\">Console</span>.WriteLine(<span style=\"color:#bc8f8f\">&quot;opening {0}&quot;</span>, <span style=\"color:#5f9ea0\">e</span>.<span style=\"color:#5f9ea0\">CurrentEntry</span>.FileName);\r\n                    <span style=\"color:#5f9ea0\">System</span>.<span style=\"color:#5f9ea0\">IO</span>.<span style=\"color:#228b22\">Stream</span> <span style=\"color:#b8860b\">s</span> = <span style=\"color:#5f9ea0\">MyStreamOpener</span>(<span style=\"color:#5f9ea0\">e</span>.<span style=\"color:#5f9ea0\">CurrentEntry</span>.FileName);\r\n                    <span style=\"color:#5f9ea0\">e</span>.<span style=\"color:#5f9ea0\">CurrentEntry</span>.InputStream = s;\r\n                }\r\n            }\r\n            <span style=\"color:#a020f0\">else</span> <span style=\"color:#a020f0\">if</span> (<span style=\"color:#5f9ea0\">e</span>.EventType == <span style=\"color:#5f9ea0\">ZipProgressEventType</span>.Saving_AfterWriteEntry)\r\n            {\r\n                <span style=\"color:#a020f0\">if</span> (<span style=\"color:#5f9ea0\">e</span>.<span style=\"color:#5f9ea0\">CurrentEntry</span>.InputStreamWasJitProvided)\r\n                {\r\n                    <span style=\"color:#5f9ea0\">Console</span>.WriteLine(<span style=\"color:#bc8f8f\">&quot;closing {0}&quot;</span>, <span style=\"color:#5f9ea0\">e</span>.<span style=\"color:#5f9ea0\">CurrentEntry</span>.FileName);\r\n                    <span style=\"color:#5f9ea0\">e</span>.<span style=\"color:#5f9ea0\">CurrentEntry</span>.<span style=\"color:#5f9ea0\">InputStream</span>.Close();\r\n                    <span style=\"color:#5f9ea0\">e</span>.<span style=\"color:#5f9ea0\">CurrentEntry</span>.<span style=\"color:#5f9ea0\">InputStream</span>.Dispose();\r\n                }\r\n            }\r\n        }\r\n</pre>\r\n<p>I put some extra properties in there to make it more convenient to use. It may be that people want to create a zip file using input from mixed sources - some from the filesystem and some from streams. In that case the library can provide some additional help to the application to help the app decide (a) whether it needs to open a stream in the BeforeWriteEntry event, and (b) whether it needs to Close/Dispose in the AfterWriteEntry event. </p>\r\n",
    "PostedDate": "2009-03-05T15:07:01.993-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "241293",
    "ThreadId": "48865",
    "Html": "<p>For those who would miss the ZipOutputStream of SharpZipLib, here is a simple code that makes it possible to use DotNetZip the &quot;regular .NET stream way&quot;.</p>\r\n<p>However, take note that it is inefficient compared to a real on-the-fly streaming solution like SharpZipLib does, as it uses an internal MemoryStream before actually calling the DotNetZip.Save() function.</p>\r\n<p>But unfortunately, SharpZibLib does not sports EAS Encryption yet (and certainly never as the project seems abandonned now).</p>\r\n<p>Let's hope that Cheeso will finally add this functionality in dotNetZip any time soon ? ;-)</p>\r\n<p>&nbsp;</p>\r\n<div style=\"color:Black;background-color:White\">\r\n<pre>    <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;summary&gt;</span>\r\n    <span style=\"color:Gray\">///</span><span style=\"color:Green\"> DotNetZip does not support streaming out-of-the-box up to version v1.8.</span>\r\n    <span style=\"color:Gray\">///</span><span style=\"color:Green\"> This wrapper class helps doing so but unfortunately it has to use</span>\r\n    <span style=\"color:Gray\">///</span><span style=\"color:Green\"> a temporary memory buffer internally which is quite inefficient</span>\r\n    <span style=\"color:Gray\">///</span><span style=\"color:Green\"> (for instance, compared with the ZipOutputStream of SharpZibLib which has other drawbacks besides).</span>\r\n    <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;/summary&gt;</span>\r\n    <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">class</span> DotNetZipOutputStream : Stream\r\n    {\r\n        <span style=\"color:Blue\">public</span> ZipFile ZipFile { <span style=\"color:Blue\">get</span>; <span style=\"color:Blue\">private</span> <span style=\"color:Blue\">set</span>; }\r\n\r\n        <span style=\"color:Blue\">private</span> MemoryStream memStream = <span style=\"color:Blue\">new</span> MemoryStream();\r\n        <span style=\"color:Blue\">private</span> String nextEntry = <span style=\"color:Blue\">null</span>;\r\n        <span style=\"color:Blue\">private</span> Stream outputStream = <span style=\"color:Blue\">null</span>;\r\n        <span style=\"color:Blue\">private</span> <span style=\"color:Blue\">bool</span> closed = <span style=\"color:Blue\">false</span>;\r\n\r\n        <span style=\"color:Blue\">public</span> DotNetZipOutputStream(Stream baseOutputStream)\r\n        {\r\n            ZipFile = <span style=\"color:Blue\">new</span> ZipFile();\r\n            outputStream = baseOutputStream;\r\n        }\r\n\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">void</span> PutNextEntry(String fileName)\r\n        {\r\n            memStream = <span style=\"color:Blue\">new</span> MemoryStream();\r\n            nextEntry = fileName;\r\n        }\r\n\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">bool</span> CanRead { <span style=\"color:Blue\">get</span> { <span style=\"color:Blue\">return</span> <span style=\"color:Blue\">false</span>; } }\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">bool</span> CanSeek { <span style=\"color:Blue\">get</span> { <span style=\"color:Blue\">return</span> <span style=\"color:Blue\">false</span>; } }\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">bool</span> CanWrite { <span style=\"color:Blue\">get</span> { <span style=\"color:Blue\">return</span> <span style=\"color:Blue\">true</span>; } }\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">long</span> Length { <span style=\"color:Blue\">get</span> { <span style=\"color:Blue\">return</span> memStream.Length; } }\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">long</span> Position\r\n        {\r\n            <span style=\"color:Blue\">get</span> { <span style=\"color:Blue\">return</span> memStream.Position; }\r\n            <span style=\"color:Blue\">set</span> { memStream.Position = value; }\r\n        }\r\n\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">void</span> Close()\r\n        {\r\n            <span style=\"color:Blue\">if</span> (closed) <span style=\"color:Blue\">return</span>;\r\n\r\n            memStream.Position = 0;\r\n            ZipFile.AddEntry(nextEntry, Path.GetDirectoryName(nextEntry), memStream);\r\n            ZipFile.Save(outputStream);\r\n            memStream.Close();\r\n            closed = <span style=\"color:Blue\">true</span>;\r\n        }\r\n\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">void</span> Flush()\r\n        {\r\n            memStream.Flush();\r\n        }\r\n\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">int</span> Read(<span style=\"color:Blue\">byte</span>[] buffer, <span style=\"color:Blue\">int</span> offset, <span style=\"color:Blue\">int</span> count)\r\n        {\r\n            <span style=\"color:Blue\">throw</span> <span style=\"color:Blue\">new</span> NotSupportedException(<span style=\"color:#A31515\">&quot;Read&quot;</span>);\r\n        }\r\n\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">long</span> Seek(<span style=\"color:Blue\">long</span> offset, SeekOrigin origin)\r\n        {\r\n            <span style=\"color:Blue\">throw</span> <span style=\"color:Blue\">new</span> NotSupportedException(<span style=\"color:#A31515\">&quot;Seek&quot;</span>);\r\n        }\r\n\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">void</span> SetLength(<span style=\"color:Blue\">long</span> value)\r\n        {\r\n            memStream.SetLength(value);\r\n        }\r\n\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">void</span> Write(<span style=\"color:Blue\">byte</span>[] buffer, <span style=\"color:Blue\">int</span> offset, <span style=\"color:Blue\">int</span> count)\r\n        {\r\n            memStream.Write(buffer, offset, count);\r\n        }\r\n    }\r\n</pre>\r\n</div>\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp;/// &lt;summary&gt;</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp;/// DotNetZip does not support streaming out-of-the-box up to version v1.8.</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp;/// This wrapper class helps doing so but unfortunately it has to use</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp;/// a temporary memory buffer internally which is quite inefficient</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp;/// (for instance, compared with the ZipOutputStream of SharpZibLib which has other drawbacks besides).</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp;/// &lt;/summary&gt;</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp;public class DotNetZipOutputStream : Stream</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp;{</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public ZipFile ZipFile { get; private set; }</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;private MemoryStream memStream = new MemoryStream();</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;private String nextEntry = null;</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;private Stream outputStream = null;</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;private bool closed = false;</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public DotNetZipOutputStream(Stream baseOutputStream)</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ZipFile = new ZipFile();</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;outputStream = baseOutputStream;</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public void PutNextEntry(String fileName)</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;memStream = new MemoryStream();</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nextEntry = fileName;</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public override bool CanRead { get { return false; } }</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public override bool CanSeek { get { return false; } }</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public override bool CanWrite { get { return true; } }</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public override long Length { get { return memStream.Length; } }</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public override long Position</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;get { return memStream.Position; }</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;set { memStream.Position = value; }</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public override void Close()</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (closed) return;</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;memStream.Position = 0;</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ZipFile.AddEntry(nextEntry, Path.GetDirectoryName(nextEntry), memStream);</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ZipFile.Save(outputStream);</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;memStream.Close();</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;closed = true;</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public override void Flush()</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;memStream.Flush();</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public override int Read(byte[] buffer, int offset, int count)</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throw new NotSupportedException(&quot;Read&quot;);</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public override long Seek(long offset, SeekOrigin origin)</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throw new NotSupportedException(&quot;Seek&quot;);</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public override void SetLength(long value)</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;memStream.SetLength(value);</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;public override void Write(byte[] buffer, int offset, int count)</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;memStream.Write(buffer, offset, count);</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">&nbsp;&nbsp; &nbsp;</div>",
    "PostedDate": "2009-10-02T07:02:59.653-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "241392",
    "ThreadId": "48865",
    "Html": "<p>&gt; Let's hope that Cheeso will finally add this functionality in dotNetZip any time soon ? ;-)</p>\r\n<p>What functionality is it, that you seek?</p>\r\n<p>Are you asking for a different programming model?&nbsp; You don't like it that DotNetZip must always Read the file or stream for content, in order save a zip file?</p>\r\n<p>&gt;&nbsp; makes it possible to use DotNetZip the &quot;regular .NET stream way&quot;.</p>\r\n<p>I'm&nbsp;do not see a clear&nbsp;benefit from this approach.&nbsp;&nbsp; It's not a &quot;regular stream&quot;.&nbsp; You have these extra methods - PutNextEntry() and so on, so a proposed DotNetZipOutputStream would not be usable in the same way any other stream is usable.&nbsp;</p>\r\n<p>One of the things I tried to do with DotNetZip even at the beginning is provide a metaphor that makes sense for zip files.&nbsp; That is the ZipFile class.&nbsp; Using a stream metaphor for the ZipFile seemed like a bad idea to me.&nbsp; It made the programming model more complicated.&nbsp; I still don't see the utility in it.</p>\r\n<p>Can you explain it to me?</p>",
    "PostedDate": "2009-10-02T10:11:39.757-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "241422",
    "ThreadId": "48865",
    "Html": "<p>I expect&nbsp;it's about&nbsp;an interface where&nbsp;the user&nbsp;can Write to a stream, not having the library Reading from a stream supplied by the user.</p>\r\n<p>When the Save method is called, and when it is time to get the bytes for&nbsp;a given&nbsp;entry, it is also natural to&nbsp;let a callback just write the bytes (e.g. from a DataSet)</p>\r\n<p>But&nbsp;I find very aggressive to speak of DotNetZip that way; it is great,&nbsp;and is more than maintained. I thank you&nbsp;Cheeso for that.</p>",
    "PostedDate": "2009-10-02T11:20:38.557-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "241452",
    "ThreadId": "48865",
    "Html": "<p>Thanks GM.</p>\r\n<p>Yes, I agree, the phrasing (&quot;finally add this functionality&quot;) may seem a bit aggressive, but I didn't take it that way.&nbsp;&nbsp;&nbsp;I do try to maintain the library, and I haven't seen any workitems covering this idea.&nbsp; I know I am not dragging my feet on this.</p>\r\n<p>What you say makes sense - allow the user to write to a stream that results in a ZipEntry in the zip file.&nbsp;&nbsp;&nbsp; I would be happy to discuss the idea to figure out a way to satisfy.&nbsp; In fact, just yesterday, someone came on the forums with this requirement.&nbsp; He wanted to save a DataSet as a zipentry in a zipfile, but he did not want to save the dataset to a file, first.&nbsp; The DataSet has a WriteXml() method, which writes to a stream.&nbsp; But DotNetZip cannot zip up the contents of a stream provided this way.&nbsp;&nbsp;My solution for that user was an AdapterStream.&nbsp; It works, but is not optimal.&nbsp; It requires the use of 2 threads, so the programming model is not so simple.</p>\r\n<p>I think there may be a way to allow this, without modifying the rest of the DotNetZip interface too heavily.&nbsp;&nbsp; I'll have to think about it.</p>\r\n<p>My first idea is to have a callout from the library to the user's application, providing a stream to which the user must write.&nbsp;&nbsp; It might mean extending <a href=\"http://cheeso.members.winisp.net/DotNetZipHelp/html/57421506-67c8-6ad2-f732-1cf5515ed8e6.htm\">ZipEntrySource</a> to include another option.</p>\r\n<p>Another idea is to introduce a new class in the way envisioned by the original poster.&nbsp; This would provide a completely&nbsp;alternative interface to DotNetZip.&nbsp; Everything would have to be duplicated - the events, all the ZipFile properties, and so on.</p>\r\n<p>&nbsp;</p>",
    "PostedDate": "2009-10-02T12:23:07.057-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "241480",
    "ThreadId": "48865",
    "Html": "<table border=0 width=800>\r\n<tbody>\r\n<tr>\r\n<td>\r\n<p>I'm considering the programming model that would be enabled with this change.</p>\r\n<div style=\"color:Black;background-color:White\">\r\n<pre>DataSet dataset1 = <span style=\"color:Blue\">new</span> DataSet();\r\ndataset1.Fill(...);\r\n<span style=\"color:Blue\">using</span> (ZipOutputStream zipos = ZipFile.OpenOutputStream(stream))\r\n{\r\n    zipos.CompressionLevel = Ionic.Zlib.CompressionLevel.Best; \r\n    zipos.Encryption = Ionic.Zip.EncryptionAlgorithm.AES256;\r\n    zipos.Password = &quot;VerySecret!&quot;;\r\n\r\n    zipos.PutNextEntry(...);     \r\n    dataset1.WriteXml(zipos);  \r\n\r\n    zipos.PutNextEntry(...); \r\n    <span style=\"color:Blue\">using</span> (Stream otherStream = OpenReadableStream())\r\n    {\r\n        <span style=\"color:Blue\">int</span> n;\r\n        <span style=\"color:Blue\">while</span> ((n= otherStream.Read(buffer, 0, buffer.Length))&gt;0)\r\n        {\r\n            zipos.Write(buffer,0,n);\r\n        }\r\n    }\r\n}\r\n</pre>\r\n</div>\r\n<p>Is that about right?&nbsp;&nbsp; or...are you thinking something else?</p>\r\n<p>I suppose within PutNextEntry one would want to be able to&nbsp;set the encryption, compression level, codepage, and so on? Or, would it be ok to keep all of those properties on the ZipOutputStream class?</p>\r\n<p>I'm still trying to envision what it would look like.&nbsp; My first reaction is: such a ZipOutputStream&nbsp;class looks very redundant with the existing ZipFile class.&nbsp; I understand that it is similar to JarOutputStream in Java, and ZipOutputStream in SharpZipLib.&nbsp; But that fact alone is not a good reason to implement it in DotNetZip.</p>\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>\r\n</td>\r\n</tr>\r\n</tbody>\r\n</table>",
    "PostedDate": "2009-10-02T13:16:31.177-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "241505",
    "ThreadId": "48865",
    "Html": "<table border=0 width=800>\r\n<tbody>\r\n<tr>\r\n<td>\r\n<p>Or maybe a better interface is:</p>\r\n<div style=\"color:Black;background-color:White\">\r\n<pre><span style=\"color:Blue\">using</span> (<span style=\"color:Blue\">var</span> zip = <span style=\"color:Blue\">new</span> <span style=\"color:#CD853F\">ZipFile</span>(output))\r\n{\r\n    zip.Encryption= <span style=\"color:#CD853F\">EncryptionAlgorithm</span>.WinZipAes256;\r\n    zip.Password = <span style=\"color:#A31515\">&quot;whatever&quot;</span>;\r\n\r\n    <span style=\"color:Blue\">using</span> (<span style=\"color:#CD853F\">ZipOutputStream</span> zipos = zip.OpenOutputStream())\r\n    {\r\n        zipos.PutNextEntry(...); <span style=\"color:Green\">// name, other attributes    </span>\r\n        dataset1.Write(zipos); \r\n\r\n        zipos.PutNextEntry(...); <span style=\"color:Green\">// name, other attributes    </span>\r\n        <span style=\"color:Blue\">using</span> (<span style=\"color:#CD853F\">Stream</span> otherStream = OpenReadableStream())\r\n        {\r\n            <span style=\"color:Blue\">int</span> n;\r\n            <span style=\"color:Blue\">while</span> ((n= otherStream.Read(buffer, 0, buffer.Length))&gt;0)\r\n            {\r\n                 zipos.Write(buffer,0,n);\r\n            }\r\n        }\r\n    }\r\n}\r\n</pre>\r\n</div>\r\n<p>In this case the ZipFile instance can dispense a ZipOutputStream, which can then be used as a regular, writable stream. Each PutNextEntry() starts a new entry. There is no Save() necessary on the ZipFile instance, because it would be written as the ZipOutputStream is written, and the zip file would be terminated when the ZipOutputStream is closed.&nbsp;</p>\r\n<p>As an alternative I don't think a constructor like this:&nbsp;</p>\r\n<div style=\"color:Black;background-color:White\">\r\n<pre><span style=\"color:Blue\">using</span> (Stream x = <span style=\"color:Blue\">new</span> ZipOutputStream(<span style=\"color:Blue\">new</span> ZipFile(output)))\r\n{\r\n   ...\r\n}\r\n</pre>\r\n</div>\r\n<p>...which inverts the construction, would make sense.&nbsp; The problem here is that the use of the ZipOutputStream changes the behavior &nbsp;&nbsp; of the ZipFile.&nbsp; Using ZipOutputStream means the zipfile is being written as calls to ZipOutputStream.Write() are made, which does not happen in the existing DotNetZip interface.&nbsp; Therefore, constructing a ZipOutputStream based on a ZipFile seems wrong.&nbsp; It would have to violate encapsulation in order to work properly. &nbsp; On the other hand, it seems ok to me, to change the state of the ZipFile, when&nbsp;using a method on the ZipFile to dispense a ZipOutputStream, as in the&nbsp;first code snip.</p>\r\n<p>Creating a ZipOutputStream is created from the ZipFile, and providing the expected semantics,&nbsp;would require some significant changes within the&nbsp;ZipFile class.&nbsp;While it wouldn't introduce redundancies with the existing interface, it <em>would </em>introduce some complexity and new pitfalls.</p>\r\n<p>For example, intermixing calls to ZipFile.AddFile() with calls to ZipFile.OpenOutputStream() would introduce some twists.&nbsp;Using ZipFile.OpenOutputStream on a zipfile with entries in it, would cause all of the existing entries to be written/saved before the call returned.&nbsp; And so&nbsp;on.&nbsp;&nbsp;Nothing impossible to solve.</p>\r\n<p>Also, is PutNextEntry really the right name for the method on the ZipOutputStream?&nbsp; How about PrepareNextEntry or StartNextEntry?&nbsp; PutNextEntry does not express what that method is doing.</p>\r\n<p>&nbsp;</p>\r\n</td>\r\n</tr>\r\n</tbody>\r\n</table>",
    "PostedDate": "2009-10-02T14:06:59.603-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "241637",
    "ThreadId": "48865",
    "Html": "<p>What would be convenient for me would be to have a constructor of ZipEntry (or a property on ZipEntry) to supply my own delagate of type Action&lt;Stream&gt; (or any other similar delegate if you don't want to depend on .Net 3.5).</p>\r\n<p>This delegate would do writes on the supplied stream, at the time the ZipEntry must be processed (inside the processing of ZipFile.Save).</p>\r\n<p>You have a Deflate implementation that would allow compression on the fly, and just have&nbsp;to pass to the delegate a Stream implementation that only allows Write (no reads, no seek) to the underlying file, and doing noting when closed/disposed.</p>",
    "PostedDate": "2009-10-03T05:50:48.42-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "241646",
    "ThreadId": "48865",
    "Html": "<p>In fact I expect that internally you are reading a Stream only to write the bytes on a deflating stream(depending on CompressionMethod). Let us access that level. Reading comes from the use case of &quot;copying&quot; a file to the zip.</p>\r\n<p>You could&nbsp;internally supply a delegate for the existing cases, or&nbsp;let the&nbsp;user supply its own. The model of providing streams on an&nbsp;event, with another event to close it, is finally not convenient to use.</p>",
    "PostedDate": "2009-10-03T06:34:57.107-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "241709",
    "ThreadId": "48865",
    "Html": "<p>yes, GM, you're right about the design.&nbsp; It reads the source stream only to write it to the DeflateStream.</p>\r\n<p>I like the idea of a delegate, I'll have to think about modifying the design to allow that.</p>\r\n<p>Up til now I have not depended on .NET 3.5.&nbsp;&nbsp;&nbsp; I don't know if I want to change that for DotNetZip v1.9.</p>",
    "PostedDate": "2009-10-03T12:52:52.2-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "241716",
    "ThreadId": "48865",
    "Html": "<p>&gt; The model of providing streams on an&nbsp;event, with another event to close it, is finally not convenient to use.</p>\r\n<p>You know, I thought about this for a while.&nbsp;&nbsp;How to provide a way to provide the stream&nbsp;just-in-time.&nbsp;&nbsp;&nbsp;I thought of providing 2 new delegate types -&nbsp;remember dotnetzip does not use .net 3.5, so I must define new types.&nbsp; This would mean one delegate type to open the stream and one delegate to close it.&nbsp; But then in the feedback I got, it seemed like too many new interfaces.&nbsp;</p>\r\n<p>I could change it, but I am still not really happy with the delegate option for opening and closing the stream.&nbsp;</p>\r\n<p>If I provide a delegate option for writing the stream ... then it makes sense to also provide a delegate to open+close the stream.&nbsp;&nbsp; Those would be exclusive alternatives, of course. When the app provides a delegate to open the stream, it is DotNetZip calling Read on that stream (and never Write).&nbsp;&nbsp; On the other hand, when the app provides a delegate to Write the zip output stream, then DotNetZip wouldn't ever Read from an application-provided stream.&nbsp; Even though they are never used together, it would make sense to have them be consistent.</p>\r\n<p>&nbsp;</p>",
    "PostedDate": "2009-10-03T13:14:27.473-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "241754",
    "ThreadId": "48865",
    "Html": "<table border=0 width=800>\r\n<tbody>\r\n<tr>\r\n<td>\r\n<p>Rather than providing a constructor, I think for consistency such an entry ought to be created with an overload of the AddEntry() method on the ZipFile class.</p>\r\n<p>The new method should accept a delegate, which is&nbsp;defined like this:</p>\r\n<div style=\"color:Black;background-color:White\">\r\n<pre><span style=\"color:Blue\">public</span> <span style=\"color:Blue\">delegate</span> <span style=\"color:Blue\">void</span> WriteDelegate(<span style=\"color:Blue\">string</span> entryName, System.IO.Stream stream);\r\n</pre>\r\n</div>\r\n<p>Here's the programming model, if you want to save a DataSet to a zip file.</p>\r\n<div style=\"color:Black;background-color:White\">\r\n<pre>DataSet ds1 = <span style=\"color:Blue\">new</span> DataSet();\r\nda.Fill(ds1, <span style=\"color:#A31515\">&quot;Invoices&quot;</span>);\r\n\r\n<span style=\"color:Blue\">using</span>(Ionic.Zip.ZipFile zip = <span style=\"color:Blue\">new</span> Ionic.Zip.ZipFile())\r\n{\r\n    zip.AddEntry(zipEntryName, (name,stream) =&gt; ds1.WriteXml(stream) );\r\n    zip.Save(zipFileName);\r\n}\r\n</pre>\r\n</div>\r\n<p>Or, for writing arbitrary data into the zip:&nbsp;</p>\r\n<div style=\"color:Black;background-color:White\">\r\n<pre><span style=\"color:Blue\">using</span> (<span style=\"color:Blue\">FileStream</span> input = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ))\r\n{\r\n    <span style=\"color:Blue\">using</span>(Ionic.Zip.ZipFile zip = <span style=\"color:Blue\">new</span> Ionic.Zip.ZipFile())\r\n    {\r\n        zip.AddEntry(zipEntryName, (name,output) =&gt;\r\n            {\r\n                <span style=\"color:Blue\">byte</span>[] buffer = <span style=\"color:Blue\">new</span> <span style=\"color:Blue\">byte</span>[BufferSize];\r\n                <span style=\"color:Blue\">int</span> n;\r\n                <span style=\"color:Blue\">while</span> ((n = input.Read(buffer, 0, buffer.Length)) != 0)\r\n                {\r\n                    output.Write(buffer, 0, n);\r\n                    <span style=\"color:Green\">// could update a progress bar here</span>\r\n                }\r\n            });\r\n\r\n        zip.Save(zipFileName);\r\n    }\r\n}\r\n\r\n\r\n</pre>\r\n</div>\r\n<p>What do you think?</p>\r\n</td>\r\n</tr>\r\n</tbody>\r\n</table>",
    "PostedDate": "2009-10-03T17:22:42.367-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "241758",
    "ThreadId": "48865",
    "Html": "This discussion has been copied to a work item. Click <a href=\"http://dotnetzip.codeplex.com/WorkItem/View.aspx?WorkItemId=8910\">here</a> to go to the work item and continue the discussion.",
    "PostedDate": "2009-10-03T17:36:30.023-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "241826",
    "ThreadId": "48865",
    "Html": "<p>ok, I implemented this change, in changeset 44426.</p>\r\n<p>download v1.9.0.12 to try it out.</p>\r\n<p>&nbsp;</p>",
    "PostedDate": "2009-10-03T23:52:17.76-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "242195",
    "ThreadId": "48865",
    "Html": "<p>First, I've got to apologize. Re-reading myself, I was definitly rude !</p>\r\n<p>Sorry. You make a wonderful job and I'm thankful for that.</p>\r\n<p>To clarify my point, I'm trying to use your library to receive and send XML data through a WCF service. Depending on metadata, the exchanged XML data are either compressed as a single-file zip archive or a deflated stream or just plain text.</p>\r\n<p>Using streams offers me to read and write the XML without worrying if it is compressed in a way or another or not at all. I'm just opening the correct chain of streams once at the beginning and then I can reuse the same path code that uses regular XmlTextReader/Writers to do the job. That's why the &quot;stream&quot; pattern suits me and why I'd like to use it with your library.</p>\r\n<p>However, I'm facing two issues using streams this way:</p>\r\n<p>- while writing, using the DotNetZipOutputStream, I'm running high on memory consumption as I need to hold the whole uncompressed data in memory before compressing.</p>\r\n<p>- while reading, the MessageBobyStream received from the WCF interface is &quot;forward-only&quot; and the ZipFile.Read(stream) function is using the Seek() method which throws an UnsupportedException.</p>\r\n<p>Unfortunately, your new AddEntry method with a delegate still does not fit with my needs, although it's great and a much better solution than the threaded StreamAdapter !.</p>\r\n<p>Cheers :-)</p>\r\n<p>&nbsp;</p>",
    "PostedDate": "2009-10-05T07:47:27.42-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "242206",
    "ThreadId": "48865",
    "Html": "<p>ok, that clarifies things.</p>\r\n<p>Why can you not save the zip file to your output stream?&nbsp;&nbsp; you have a stream, or a chain of streams, right?&nbsp; And you write to the outer-most stream., yes? why can you not just call ZipFile.Save(stream) ??</p>\r\n<p>I don't really see the utility in sending a single-file zip archive.&nbsp; A deflated stream makes sense to me.&nbsp; &nbsp;Why would you want a single-file zip archive?&nbsp; It seems to offer no advantage over the DeflateStream approach.</p>\r\n<p>&nbsp;</p>",
    "PostedDate": "2009-10-05T08:15:26.903-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "242225",
    "ThreadId": "48865",
    "Html": "<p>The idea behind the single-zip archive thing is to be able to use the password protection with AES encryption to enforce the security the XML data stored on the client side before it is sent to the server. This is not directly related with the security of WCF services but&nbsp;I've got to deal with it at the other end as it is sent &quot;as is&quot;.</p>\r\n<p>About the ZipFile.Save(stream), it would mean that depending of the type of the source stream, I will have to pass the ZipFile object to my business layer that will have to know about it and whether it has to be called or not when it finishes its work. I would prefer that the business layer to deal only with raw XML data as a pivot, being unaware of encryption, authentication and protocols logic and details.</p>\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>",
    "PostedDate": "2009-10-05T08:49:52.207-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "242244",
    "ThreadId": "48865",
    "Html": "<table border=0 width=800>\r\n<tbody>\r\n<tr>\r\n<td>\r\n<p>Ah, things are a little clearer.&nbsp; What you want is a stream that does Aes encryption.&nbsp; The ZipFile is not suitable for that purpose.</p>\r\n<p>&gt; to enforce the security the XML data stored on the client side before it is sent to the server. This is not directly related with the security of WCF services but&nbsp;I've got to deal with it at the other end as it is sent &quot;as is&quot;.</p>\r\n<p>I don't understand what this means.&nbsp; In WCF there is the possibility to encrypt the transmitted data on the sending side, and decrypt on the receiving side.&nbsp; Why not use the builtin capability?&nbsp;&nbsp;</p>\r\n<p>&gt;&nbsp;I would prefer that the business layer to deal only with raw XML data as a pivot, being unaware of encryption, authentication and protocols logic and details.</p>\r\n<p>But if you use the ZipOutputStream you provided above, your logic must call PutNextEntry() when writing to the zipOutputStream, right?&nbsp; And you must set the Password and the Encryption properties on the ZipFile.&nbsp; So is there knowledge of the ZipOutputStream in your code?&nbsp; There must be.</p>\r\n<p>&nbsp;</p>\r\n</td>\r\n</tr>\r\n</tbody>\r\n</table>",
    "PostedDate": "2009-10-05T10:04:36.49-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "242269",
    "ThreadId": "48865",
    "Html": "<p>boutblock, I think you want to do something like this:</p>\r\n<div style=\"color:Black;background-color:White\">\r\n<pre><span style=\"color:Blue\">using</span> (<span style=\"color:Blue\">var</span> input = File.Open(_inputFileName, FileMode.Open ))\r\n{\r\n    <span style=\"color:Blue\">using</span> (<span style=\"color:Blue\">var</span> raw = File.Open(_outputFileName, FileMode.Create, FileAccess.ReadWrite ))\r\n    {\r\n        <span style=\"color:Blue\">using</span> (<span style=\"color:Blue\">var</span> output= <span style=\"color:Blue\">new</span> DotNetZipOneEntryOutputStream(raw, _inputFileName))\r\n        {\r\n            output.Password = _password;\r\n\r\n            <span style=\"color:Blue\">byte</span>[] buffer= <span style=\"color:Blue\">new</span> <span style=\"color:Blue\">byte</span>[2048];\r\n            <span style=\"color:Blue\">int</span> n;\r\n            <span style=\"color:Blue\">while</span> ((n= input.Read(buffer,0,buffer.Length)) &gt; 0)\r\n            {\r\n                output.Write(buffer,0,n);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\n</pre>\r\n</div>\r\n<p>is that right?&nbsp; if so, here's a class that will help you.&nbsp; It depends on the new feature added in v1.9.0.12.&nbsp; There's no MemoryStream used to buffer the writes. Instead it uses a background thread to do the save.</p>\r\n<div style=\"color:Black;background-color:White\">\r\n<pre>    <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;summary&gt;</span>\r\n    <span style=\"color:Gray\">///</span><span style=\"color:Green\"> DotNetZip does not provide a ZipOutputStream, like SharpZipLib.</span>\r\n    <span style=\"color:Gray\">///</span><span style=\"color:Green\"> This wrapper class provides one, which supports a single entry only.</span>\r\n    <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;/summary&gt;</span>\r\n    <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">class</span> DotNetZipOneEntryOutputStream : Stream\r\n    {\r\n        <span style=\"color:Blue\">private</span> String _password;\r\n        <span style=\"color:Blue\">private</span> String _entryName;\r\n        <span style=\"color:Blue\">private</span> Stream _outputStream;\r\n        <span style=\"color:Blue\">private</span> Stream _entryStream;\r\n        <span style=\"color:Blue\">private</span> ZipEntry _zipEntry;\r\n        <span style=\"color:Blue\">private</span> <span style=\"color:Blue\">bool</span> _closed;\r\n        <span style=\"color:Blue\">private</span> System.Threading.ManualResetEvent _hasClosed;\r\n        <span style=\"color:Blue\">private</span> System.Threading.ManualResetEvent _streamIsSet;\r\n        <span style=\"color:Blue\">private</span> System.Threading.ManualResetEvent _doneSaving;\r\n\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;summary&gt;</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> Create a DotNetZipOneEntryOutputStream.</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;/summary&gt;</span>\r\n        <span style=\"color:Gray\">///</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;remarks&gt;</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> The resulting zip file will contain just one entry, with the specified</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> name.  </span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;/remarks&gt;</span>\r\n        <span style=\"color:Gray\">///</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;param name=&quot;s&quot;&gt;</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> The stream to wrap.</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;/param&gt;</span>\r\n        <span style=\"color:Gray\">///</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;param name=&quot;entryName&quot;&gt;</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> The name of the entry to create in the zip file.</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;/param&gt;</span>\r\n        <span style=\"color:Blue\">public</span> DotNetZipOneEntryOutputStream(Stream s, <span style=\"color:Blue\">string</span> entryName)\r\n            : <span style=\"color:Blue\">this</span> (s, entryName, <span style=\"color:Blue\">null</span>) { }\r\n\r\n        \r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;summary&gt;</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> Create a password-protected DotNetZipOneEntryOutputStream.</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;/summary&gt;</span>\r\n        <span style=\"color:Gray\">///</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;remarks&gt;</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> This class uses WinZipAes256 encryption when the password is</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> non-null. The resulting zip file will contain just one</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> entry, with the specified name, and encrypted using AES</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> using the specified password.</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;/remarks&gt;</span>\r\n        <span style=\"color:Gray\">///</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;param name=&quot;s&quot;&gt;</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> The stream to wrap.</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;/param&gt;</span>\r\n        <span style=\"color:Gray\">///</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;param name=&quot;entryName&quot;&gt;</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> The name of the entry to create in the zip file.</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;/param&gt;</span>\r\n        <span style=\"color:Gray\">///</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;param name=&quot;password&quot;&gt;</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> The password to use to encrypt the entry in the zip file.</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;/param&gt;</span>\r\n        <span style=\"color:Blue\">public</span> DotNetZipOneEntryOutputStream(Stream s, <span style=\"color:Blue\">string</span> entryName, <span style=\"color:Blue\">string</span> password)\r\n        {\r\n            _hasClosed = <span style=\"color:Blue\">new</span> System.Threading.ManualResetEvent(<span style=\"color:Blue\">false</span>);\r\n            _streamIsSet = <span style=\"color:Blue\">new</span> System.Threading.ManualResetEvent(<span style=\"color:Blue\">false</span>);\r\n            _doneSaving = <span style=\"color:Blue\">new</span> System.Threading.ManualResetEvent(<span style=\"color:Blue\">false</span>);\r\n\r\n            _entryName = entryName;\r\n            _outputStream = s;\r\n            _password = password;\r\n            \r\n            ThreadPool.QueueUserWorkItem(<span style=\"color:Blue\">new</span> WaitCallback(SaveWhenDoneWriting), <span style=\"color:Blue\">null</span>);\r\n            _streamIsSet.WaitOne();\r\n        }\r\n\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;summary&gt;</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> The password to use on the entry in the zip file.</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;/summary&gt;</span>\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">string</span> Password\r\n        {\r\n            <span style=\"color:Blue\">set</span>\r\n            {\r\n                _password = value; \r\n                _zipEntry.Password = _password;\r\n                _zipEntry.Encryption = (_password == <span style=\"color:Blue\">null</span>)\r\n                    ? EncryptionAlgorithm.None\r\n                    : EncryptionAlgorithm.WinZipAes256;\r\n            }\r\n        }\r\n\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;summary&gt;</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> The name of the entry in the zip file.</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;/summary&gt;</span>\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">string</span> EntryName\r\n        {\r\n            <span style=\"color:Blue\">get</span> \r\n            {\r\n                <span style=\"color:Blue\">return</span> _entryName;\r\n            }\r\n            <span style=\"color:Blue\">set</span>\r\n            {\r\n                <span style=\"color:Blue\">if</span> (value == <span style=\"color:Blue\">null</span>)\r\n                    <span style=\"color:Blue\">throw</span> <span style=\"color:Blue\">new</span> ArgumentException(<span style=\"color:#A31515\">&quot;EntryName&quot;</span>);\r\n                _entryName = value;\r\n                _zipEntry.FileName = _entryName;\r\n            }\r\n        }\r\n\r\n        \r\n        <span style=\"color:Blue\">private</span> <span style=\"color:Blue\">void</span> SaveWhenDoneWriting(<span style=\"color:Blue\">object</span> o)\r\n        {\r\n            <span style=\"color:Blue\">using</span> (<span style=\"color:Blue\">var</span> zipFile = <span style=\"color:Blue\">new</span> ZipFile())\r\n            {\r\n                _zipEntry = zipFile.AddEntry(EntryName, (name, stream) =&gt;\r\n                    {\r\n                        _entryStream = stream;\r\n                        _streamIsSet.Set();\r\n                        _hasClosed.WaitOne();\r\n                    }\r\n                                             );\r\n                <span style=\"color:Blue\">if</span> (_password != <span style=\"color:Blue\">null</span>)\r\n                {\r\n                    _zipEntry.Password = _password;\r\n                    _zipEntry.Encryption = EncryptionAlgorithm.WinZipAes256;\r\n                }\r\n                \r\n                zipFile.Save(_outputStream);\r\n            }\r\n            _doneSaving.Set();\r\n        }\r\n\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;summary&gt;</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> Write the data from the buffer to the stream.</span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;/summary&gt;</span>\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">void</span> Write(<span style=\"color:Blue\">byte</span>[] buffer, <span style=\"color:Blue\">int</span> offset, <span style=\"color:Blue\">int</span> count)\r\n        {\r\n            <span style=\"color:Blue\">if</span> (_closed) <span style=\"color:Blue\">throw</span> <span style=\"color:Blue\">new</span> System.InvalidOperationException();\r\n            _entryStream.Write(buffer,offset,count);\r\n        }\r\n\r\n        \r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;summary&gt;</span>\r\n        <span style=\"color:Gray\">///</span><span style=\"color:Green\"> Close the stream. </span>\r\n        <span style=\"color:Gray\">///</span> <span style=\"color:Gray\">&lt;/summary&gt;</span>\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">void</span> Close()\r\n        {\r\n            <span style=\"color:Blue\">if</span> (_closed) <span style=\"color:Blue\">return</span>;\r\n            _hasClosed.Set();\r\n            _closed= <span style=\"color:Blue\">true</span>;\r\n            _doneSaving.WaitOne();\r\n        }\r\n\r\n\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">bool</span> CanRead  { <span style=\"color:Blue\">get</span> { <span style=\"color:Blue\">return</span> <span style=\"color:Blue\">false</span>; } }\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">bool</span> CanSeek  { <span style=\"color:Blue\">get</span> { <span style=\"color:Blue\">return</span> <span style=\"color:Blue\">false</span>; } }\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">bool</span> CanWrite { <span style=\"color:Blue\">get</span> { <span style=\"color:Blue\">return</span> <span style=\"color:Blue\">true</span>; } }\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">long</span> Length   { <span style=\"color:Blue\">get</span> { <span style=\"color:Blue\">throw</span> <span style=\"color:Blue\">new</span> NotSupportedException(); }}\r\n\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">long</span> Position\r\n        {\r\n            <span style=\"color:Blue\">get</span> { <span style=\"color:Blue\">throw</span> <span style=\"color:Blue\">new</span> NotSupportedException();}\r\n            <span style=\"color:Blue\">set</span> { <span style=\"color:Blue\">throw</span> <span style=\"color:Blue\">new</span> NotSupportedException();}\r\n        }\r\n\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">void</span> Flush() { }\r\n\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">int</span> Read(<span style=\"color:Blue\">byte</span>[] buffer, <span style=\"color:Blue\">int</span> offset, <span style=\"color:Blue\">int</span> count)\r\n        {\r\n            <span style=\"color:Blue\">throw</span> <span style=\"color:Blue\">new</span> NotSupportedException(<span style=\"color:#A31515\">&quot;Read&quot;</span>);\r\n        }\r\n\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">long</span> Seek(<span style=\"color:Blue\">long</span> offset, SeekOrigin origin)\r\n        {\r\n            <span style=\"color:Blue\">throw</span> <span style=\"color:Blue\">new</span> NotSupportedException(<span style=\"color:#A31515\">&quot;Seek&quot;</span>);\r\n        }\r\n\r\n        <span style=\"color:Blue\">public</span> <span style=\"color:Blue\">override</span> <span style=\"color:Blue\">void</span> SetLength(<span style=\"color:Blue\">long</span> value)\r\n        {\r\n            <span style=\"color:Blue\">throw</span> <span style=\"color:Blue\">new</span> NotSupportedException();\r\n        }\r\n    }\r\n\r\n\r\n</pre>\r\n</div>",
    "PostedDate": "2009-10-05T12:06:52.437-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "242310",
    "ThreadId": "48865",
    "Html": "<p>the XML data are persisted &nbsp;on the client side as zip archives to handle the case when the server is unavailable.</p>\r\n<p>Therefore, the password and encryption for security reasons. WCF adds its own security over the streams exchanged.</p>\r\n<p>And yes, I have to set the password, NextEntry and so on, but I do that during initialization of the chain of streams.</p>\r\n<p>My business layer only accept an open abstract Stream as a parameter (as unfortunately IStream does not exist in the framework...).</p>\r\n<p>I will try your new&nbsp;<span style=\"font-family:Consolas, 'Courier New', Courier, monospace;white-space:pre\">DotNetZipOneEntryOutputStream as soon as ... I ll be back to work !</span></p>\r\n<p><span style=\"font-family:Consolas, 'Courier New', Courier, monospace\"><span style=\"white-space:pre\"><span style=\"font-family:'Segoe UI', 'Microsoft Sans Serif', Arial, Geneva, sans-serif\"><span style=\"white-space:normal\">Don't you ever sleep or at least have a quick nap !! lol</span></span></span></span></p>\r\n<p><span style=\"font-family:Consolas, 'Courier New', Courier, monospace\"><span style=\"white-space:pre\"><span style=\"font-family:'Segoe UI', 'Microsoft Sans Serif', Arial, Geneva, sans-serif\"><span style=\"white-space:normal\"><br></span></span></span></span></p>",
    "PostedDate": "2009-10-05T14:45:21.897-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "242407",
    "ThreadId": "48865",
    "Html": "<p>No, I don't sleep!!</p>\r\n<p>I put a ZipOutputStream into DotNetZip - try it out. You need v1.9.0.13.</p>",
    "PostedDate": "2009-10-05T22:15:00.317-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "242469",
    "ThreadId": "48865",
    "Html": "<p>Ok, I'm gonna try it now, thx a lot.</p>\r\n<p>Btw, would be abusing to ask for a ZipInputStream that deals with forward-only streams ? ;-)</p>",
    "PostedDate": "2009-10-06T02:05:41.073-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "242481",
    "ThreadId": "48865",
    "Html": "<p>Great ! I've replaced my own implementation based on a memory stream and it's working perfectly :-)</p>\r\n<p>Now, If there is a way to workaround the forward-only input stream issue without using a temporary memory stream as I did, this would allow no limit in size of data exchanged by using streams in both directions of my WCF interface :-)</p>\r\n<p>PS : my current version of Winrar 2.62 cannot open the zip archive with 256 bits AES encryption enabled (but hey, winrar is made for RAR not ZIP format ;-). However 7Zip 4.65 does perfectly.</p>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">! &nbsp; H:\\v_xps_ifsv2\\TPI\\XmlFileTransfer.WCF.Net\\ClientTest\\bin\\Debug\\Download\\FinancialTransactions_20080101_20110101.xml.zip: Unknown method in FinancialTransactions_20080101_20110101.xml</div>\r\n<div id=\"_mcePaste\" style=\"left:-10000px;top:0px;width:1px;height:1px;overflow-x:hidden;overflow-y:hidden\">! &nbsp; H:\\v_xps_ifsv2\\TPI\\XmlFileTransfer.WCF.Net\\ClientTest\\bin\\Debug\\Download\\FinancialTransactions_20080101_20110101.xml.zip: No files to extrac</div>\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>",
    "PostedDate": "2009-10-06T02:52:07.373-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "242788",
    "ThreadId": "48865",
    "Html": "<table border=0 width=800>\r\n<tbody>\r\n<tr>\r\n<td>\r\n<blockquote style=\"border:solid .1em #ccc;font-style:italic;margin:.25em 1em 0 1em;padding:0 .25em 0 .25em\"><strong>boutblock wrote:</strong><br>\r\n<p>Now, If there is a way to workaround the forward-only input stream issue without using a temporary memory stream as I did, this would allow no limit in size of data exchanged by using streams in both directions of my WCF interface :-)</p>\r\n<div id=\"_mcePaste\" style=\"overflow-x:hidden;overflow-y:hidden;width:1px;height:1px;top:0px;left:-10000px\">! &nbsp; H:\\v_xps_ifsv2\\TPI\\XmlFileTransfer.WCF.Net\\ClientTest\\bin\\Debug\\Download\\FinancialTransactions_20080101_20110101.xml.zip: No files to extrac</div>\r\n</blockquote>\r\n<p>Are you referring to the fact that it is not possible to use PKZIP encryption when using a ZipOutputStream?&nbsp;&nbsp; <em>If you are...</em></p>\r\n<blockquote style=\"border:dashed .1em #ddd;padding:.4em\">\r\n<p>Is this a big problem?</p>\r\n<p>I don't know if you read the doc I wrote on this topic.&nbsp; I tried to explain it there.&nbsp; In short, the reason PKZIP encryption doesn't work with a ZipOutputStream is that the initial Encryption &quot;seed&quot; depends on the CRC of the data to be encrypted.&nbsp; And of course the library can only learn the CRC after all the data has been streamed.&nbsp;&nbsp;</p>\r\n<p>The WinZip AES encryption does not have this problem.</p>\r\n<p>I thought about how to get around this problem.&nbsp; The library could cache all the data that is streamed, then compute the CRC, then write the data through the encryptor.&nbsp; This will work for small data sizes, not for large ones.&nbsp; You'll get a memory error.&nbsp; I think you saw that.</p>\r\n<p>The other option is to invent a programming model where the application must stream the data twice.&nbsp; First to compute the CRC, then again to actually perform the encryption.&nbsp; This would be really ugly, I think.&nbsp; It would break the feel of the &quot;stream&quot; interface.&nbsp;</p>\r\n</blockquote>\r\n<p>If you are talking about something else, please explain.</p>\r\n<p>-Cheeso</p>\r\n</td>\r\n</tr>\r\n</tbody>\r\n</table>",
    "PostedDate": "2009-10-06T21:13:54.467-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "242789",
    "ThreadId": "48865",
    "Html": "<p>oh, wait, I think you are asking for a ZipInputStream, is that right?</p>\r\n<p>Yeah, I figured that would be the next step.&nbsp;&nbsp; I'll see what I can do.</p>\r\n<p>&nbsp;</p>",
    "PostedDate": "2009-10-06T21:15:29.327-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "242790",
    "ThreadId": "48865",
    "Html": "This discussion has been copied to a work item. Click <a href=\"http://dotnetzip.codeplex.com/WorkItem/View.aspx?WorkItemId=8926\">here</a> to go to the work item and continue the discussion.",
    "PostedDate": "2009-10-06T21:16:22.963-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "242876",
    "ThreadId": "48865",
    "Html": "<p>Yeah, that's what I figured out about the legacy PKZIP encryption, that it wouldn't be compatible with a forward-only writing stream.</p>\r\n<p>But that's fine with me as the AES Encryption was what I needed in the first place.</p>\r\n<p>I don't think you should bother with this old and weak PKZIP encryption while dealing with streams anyway.</p>\r\n<p>&nbsp;</p>\r\n<p>Regarding the ZipInputStream, well yes, that would make DotNetZip the most complete Zip library for .NET !</p>\r\n<p>And I already have to thank you a lot for your responsiveness. You beat most of the commercial supports out there !</p>\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>",
    "PostedDate": "2009-10-07T02:15:33.28-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  }
]