Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Write with ObjectOutputStream into multiple ZipEntrys in a single ZipOutputStream

I want to create a zip archive in Java where each contained file is produced by serializing some objects. I have a problem with correctly closing the streams.

The code looks like this:

try (OutputStream os = new FileOutputStream(file);
     ZipOutputStream zos = new ZipOutputStream(os);) {

  ZipEntry ze;
  ObjectOutputStream oos;

  ze = new ZipEntry("file1");
  zos.putNextEntry(ze); // start first file in zip archive
  oos = new ObjectOutputStream(zos);
  oos.writeObject(obj1a);
  oos.writeObject(obj1b);
  // I want to close oos here without closing zos
  zos.closeEntry(); // end first file in zip archive

  ze = new ZipEntry("file2");
  zos.putNextEntry(ze); // start second file in zip archive
  oos = new ObjectOutputStream(zos);
  oos.writeObject(obj2a);
  oos.writeObject(obj2b);
  // And here again
  zos.closeEntry(); // end second file in zip archive
}

I know of course that I should close each stream after finishing using it, so I should close the ObjectOutputStreams in the indicated positions. However, closing the ObjectOutputStreams would also close the ZipOutputStream that I still need.

I do not want to omit the call to ObjectOutputStream.close() because I do not want to rely on the fact that it currently does not more than flush() and reset().

I also cannot use a single ObjectOutputStream instance because then I miss the stream header that is written by the constructor (each single file in the zip archive would not be a full object serialization file, and I could not de-serialize them independently).

The same problem occurs when reading the file again.

The only way I see would be to wrap the ZipOutputStream in some kind of "CloseProtectionOutputStream" that would forward all methods except close() before giving it to the ObjectOutputStream. However, this seems rather hacky and I wonder if I missed a nicer solution in the API.

like image 727
Philipp Wendler Avatar asked Apr 09 '13 16:04

Philipp Wendler


1 Answers

If your OutputStream wrapper throws an exception when closed more than once, it is not a hack. You can create a wrapper for each zip entry.

From an architectural point of view, I think the ObjectOutputStream author should have provided an option to disable close() cascading. You are just workarounding his lacking API.

like image 89
olivieradam666 Avatar answered Sep 30 '22 12:09

olivieradam666