srikanth-lingala / zip4j

A Java library for zip files and streams
Apache License 2.0
2.01k stars 307 forks source link

Seeking Clarification on Entry Size with STORE Compression #475

Open jacob-fw opened 1 year ago

jacob-fw commented 1 year ago

Just want to specify this upfront. I have done my best to try and understand what's going on before posting here, so if there's something I'm missing, please feel free to correct me.

I've read several of the other threads people have brought up related to the requirement to set the entry size when using CompressionMethods.STORE https://github.com/srikanth-lingala/zip4j/issues/10 https://github.com/srikanth-lingala/zip4j/issues/11

Had to read them a few times before it finally clicked for me, but I do see why it is desired; in order to keep the stream generated by ZipOutputStream usable by ZipInputStream. From what was in those tickets though, it does sound like the zip file structure does allow for the possibility of ZipOutputStream not needing to have the entry size specified upfront for the STORE compression method. I'm looking to use ZipOutputStream to send out a completed zipfile, and don't need the final result to be able to be read by ZipInputStream, and depending upon the data I'm adding to the zip file, I would like to be able to choose which files get compressed and which don't.

To be clear I'm not asking to change the default behavior; I think the current option of requiring all entries to be streamable is completely reasonable, and allows for maximum compatibility of how the final zip file can be used. But I also don't see why we can't have additional flexibility, especially when it sounds like 99% of what is needed is already there.

My suggestion is to add a new field to ZipParameters, StreamableEntry. For backwards compatibility it will be true by default, but in cases where we want to add a file with STORE compressionMethod (which it seems like is really the only case where it would be needed as of now) and can't specify the entry size upfront, we can set it to false.

Here's an example of how I think it could be used. `

    zos = new ZipOutputStream();

zipparam = new ZipParameters();
zipparam.setCompressionMethod(CompressionMethod.STORE);
zipparam.setStreamableEntry(false);    // NEW METHOD
zipparam.setFileNameInZip(filename);

zos.putNextEntry(zipparam);  // local file header has length set to 0
copyStream(entryStream, zos);  // copy our arbitrary length data.
zos.closeEntry();  // data descriptor has the full size written to it
    zos.close();  // File headers are written at the end

`

Again, if there's something I'm misunderstanding about Zip4J or about how the Zip Structure works ,please feel free to correct me.

srikanth-lingala commented 1 year ago

I am answering this post quite late, but maybe it might help you if you are still looking into it or maybe someone else looking into a similar issue.

I'm looking to use ZipOutputStream to send out a completed zipfile, and don't need the final result to be able to be read by ZipInputStream

if I understand right, you want to create a zip file with ZipOutputStream and don't necessarily want the final result to be a valid zip file?

But in your subsequent statements, the way I understood is that you want to add an entry to a zip file with STORE compression without knowing the size of the entry, right? This might be a little tricky because this will make this zip file incompatible to the zip specification, and most likely a lot of other zip tools will be unable to extract the zip file. There have to be changes made even in zip4j to be able to extract such file. And quite honestly, as this breaks zip specification compatibility, I am inclined not to introduce such a change.