Why is calling PutNextEntry required on ZipOutputStream?

Aug 11, 2011 at 7:36 PM

I have read the doc on the technical reasons why you have to call this before calling Write, but I am not sure why they exist.

If I want to just compress a single stream into another stream (any stream may not be a file) I don't care about an actual entry, so I have to set this to something and when dealing with two streams and neither are files I have no way to safely determine this. 

I was wondering if there are any good work around for treating a ZipOutputStream like the GZipStream basically.  Where there will only be one item in the file that is compressed.

Aug 11, 2011 at 7:40 PM

The Zip file has a structure called an "entry" in it.  This is described in the specification for ZIP file structures, which is a document put out by PKWare.  The ZIP spec says that each item in a zipfile is an entry, and each entry has a name.

The zipfile archive structure doesn't say that entries must correspond to files, or must be filled with compressed data that originated within a file. BUT, the zip spec says each entry has a name. 

That's why you need to call ZipOutputStream.PutNextEntry()

I'm not sure what you mean by "work around".  I don't see the problem you are trying to solve.   If you want a 1-item compressed archive, use GZipStream, or DeflateStream, or ZlibStream.  If you want to produce a zip archive, you can use ZipOutputStream. 


Aug 11, 2011 at 7:49 PM

Okay let me rephrase... why does PutNextEntry require a stirng?  That is my real issue, I understand the Zip format and the concept of Entries, but as I stated when you are dealing with streams that are not FileStreams then you don't have easy to use "entryName" like a file name would be.  Why can't I just a single entry with out a name?

Aug 11, 2011 at 8:56 PM

I don't understand your confusion. Maybe I was not clear, so I will just state in a different way what I wrote earlier.  PutNextEntry() accepts a name because each entry in a zipfile requires a name.  A zipfile consists of entries, each of which has a name.  PutNextEntry is the way for your app to say, "here comes a new entry (and its name is XXXX)" .

The issue of whether an arbitrary stream in your .NET application has a name associated to it has nothing to do with the zipfile structure.  The zipfile structure is what it is; the ZipOutputStream class in DotNetZip is shaped the way it is, in order to expose the zipfile structure in a usable way to applications. Each entry in a zip requires a name; when creating zip files, it's up to you and your app to decide what to specify for the name on each entry. 

As I said, if you have only one item in the compressed archive, then you may want to consider using a bare GZipStream in lieu of a ZipOutputStream. The GZipStream accepts only one compressed blob, and there's no need to specify a name for it.

Aug 11, 2011 at 9:07 PM

First Zip is better than GZip at compression so that would be a good reason not to use GZip even if its a single item or non-file streams.

Also I am just asking I guess why does an entry require a name, can I make it an empty string or null? I mean when I extra the files I don't have to extract by name if I don't want to.  

I have working code, just had this odd issue comes up in a corner case dealing with a non-file stream and I cannot get a "name" that the call would understand, so I can create a new Guid, or a default string like "Unknown" but it seems like I have to give it something. So that triggered me to ask the question, I am perfectly okay if a non-empty non-null string is required, figured it couldn't hurt to ask about it though. :)

Aug 11, 2011 at 9:14 PM

> First Zip is better than GZip at compression

Not true.  In most cases, Zip merely wraps the DeflateStream, which is essentially the same as GZipStream.  Think of a Zip as a container around multiple DeflateStreams. It is not "better" in compression.  It's a box that holds smaller compressed boxes. For one file, normally GZipStream will be smaller than a zipfile.  

> Also I am just asking I guess why does an entry require a name,

I understand what you are asking.  You have asked three times. I have responded directly and clearly to your question, twice. The answer is still the same, so I won't repeat it here.

> can I make it an empty string or null?

I think not. Try it and see, but I would expect an exception to be thrown somewhere. The entry needs a name.