0

My goal is to write an object to zip file in json format. The simplest way of doing it is:

ZipOutputStream zip = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
String json = gson.toJson(object);
zip.write(json.getBytes());

But I want to avoid to load the whole object to a single string. So I wrapped a zip stream into a writer object:

Writer writer = new OutputStreamWriter(zip);

And after that I write the entry in the following way:

zip.putNextEntry(entry);
gson.toJson(content, writer);
writer.flush();
zip.closeEntry();
zip.flush();

It works fine, but it seems very messy using writer and zip objects at the same time. Is there any better solution for this problem?

IQV
  • 500
  • 6
  • 14
lukasz
  • 41
  • 2
  • 6
  • 5
    So what is your question? – BackSlash Mar 02 '18 at 08:19
  • Sorry but by accident I've published unfinished post. Now the question should be clear. – lukasz Mar 02 '18 at 08:31
  • Assuming the json is in the default UTF-8, use `Writer writer = new OutputStreamWriter(zip, StandardCharsets.UTF_8);`. I would create the writer after putNextEntry for coherence. But in principle the code is indeed okay; writer should not be closed before zip as it would prematurely close zip. – Joop Eggen Mar 02 '18 at 08:34
  • 2
    I would not call this "messy" at all. Absolutely normal. – lexicore Mar 02 '18 at 09:03

2 Answers2

2

You can make it a bit simplier with Jackson which has methods to write directly to an OutputStream

ObjectMapper mapper = new ObjectMapper();
try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile))){  
  out.putNextEntry(new ZipEntry("object.json"));
  mapper.writeValue(out, object);
}
Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
1

You may declare one or more resources in a try-with-resources statement. For example

try (
   ZipOutputStream zip = new ZipOutputStream(new BufferedOutputStream(new 
   FileOutputStream(zipFile)));
   Writer writer = new OutputStreamWriter(zip);
) {
   zip.putNextEntry(entry);
   gson.toJson(content, writer);
}

The close methods are automatically called in this order. Note that the close methods of resources are called in the opposite order of their creation. With regards to flush, close flush it first.

public abstract void close() throws IOException

Closes the stream, flushing it first. Once the stream has been closed, further write() or flush() invocations will cause an IOException to be thrown. Closing a previously closed stream has no effect.

fabfas
  • 2,200
  • 1
  • 21
  • 21