#2807 write to zip as stored

Wolf K. Wed 15 Jul 2020

Hi, I need to write several files to a zip file, but one of them must be written as is (stored, not deflated).

How can I achieve this?

Couldnt find an option for writing stored.

brian Wed 15 Jul 2020

Do you have the code in Java which will solve your problem we could look at?

Wolf K. Wed 15 Jul 2020

Of course I prefer Fantom over Java. However, I tried to solve this by using javaffi. This is what I came up with:

using [java] java.util.zip
using [java] java.io
using [java] fanx.interop::ByteArray
using [java] java.nio.charset

class JZip {
    new make() { }

    Void storeEntry(Str zipfile, Str filename, Str content) {
	FileOutputStream fos := FileOutputStream(zipfile)
	BufferedOutputStream bos := BufferedOutputStream(fos)
	ZipOutputStream zos := ZipOutputStream(bos, StandardCharsets.UTF_8)
	try {
		ZipEntry ze := ZipEntry(filename)
		CRC32 crc := CRC32()
		Int c := 0
		ByteArray ba := ByteArray(content.size)
		content.chars.each {ba[c] = it;c++}
	} finally {

Works, but I ran into other problems: this code doesnt handle UTF-8 correctly. So I feel it would be much better if it could be done in (pure) Fantom...

SlimerDude Thu 16 Jul 2020

Just noting this is a similar request to the Parameters for deflateOutStream forum post where STORED (non-)compressed .zip entries was asked for to create epub files.

brian Mon 20 Jul 2020

I added an opts parameter to Zip.writeNext that will let you pass through the various options to the underlying Java API. With that change you can pass thru an explicit CRC, level, etc.

Wolf K. Fri 24 Jul 2020

Hi brian, thank you very much! That will be really great. Can the change be included in the next fantom version (1.0.75)?

SlimerDude Mon 27 Jul 2020

Hi Wolf K.,

I can confirm the change is committed to the master branch so should be in the Fantom-1.0.75 release.

But if you can't wait that long, I've create a preview build for you that should contain the updates: fantom-1.0.75-preview-2807.zip

The new options for Zip.writeNext() look like this:

** Append a new file to the end of this zip file and return an OutStream
** which may be used to write the file contents.  The Uri must not contain
** a query or fragment; it may optionally start with a slash.  Closing the
** OutStream will close only this file entry - use Zip.close() when finished
** writing the entire zip file.  Throw UnsupportedErr if zip is not writing
** to an output stream.
** Next entry options:
**   - comment: Str entry comment
**   - crc: Int CRC-32 of the uncompressed data
**   - extra: Buf for extra bytes data field
**   - level: Int between 9 (best compression) to 0 (no compression)
**   - compressedSize: Int for compressed size of data
**   - uncompressedSize: Int for uncompressed size of data
** NOTE: setting level to 0 sets method to STORE, else to DEFLATED.
** Examples:
**   out := zip.writeNext(`/docs/test.txt`)
**   out.writeLine("test")
**   out.close
OutStream writeNext(Uri path, DateTime modifyTime := DateTime.now,  [Str:Obj?]? opts := null)

Wolf K. Mon 3 Aug 2020

Hi SlimerDude, Hi brian,

checked out the preview and it works smoothly. All problems I had with writing (stored) zip files (including problems with UTF-8) are gone now. I'm really happy with that change and appreciate your effort.

Thank you again very much for your great work!

Login or Signup to reply.