Trying to create a ZIP file having 3 files inside it. I am using ZipOutputStream for creating ZIP file and Printwriter to create and write files into Zip.
When i close printwriter object after writing a file closes the stream as well, which i know. But if i close zip output stream after writing into zip will it close and clean my printwriter objects as well
def main(args: Array[String]): Unit = {
val file: File = new File("Hello.zip")
val zos: ZipOutputStream = new ZipOutputStream(new FileOutputStream(file))
val fileNames = Array("Happy1.csv", "Happy2.csv", "Happy3.csv", "Happy4.csv")
fileNames.foreach { tempfile =>
zos.putNextEntry(new ZipEntry(tempfile))
Try {
val writer = new PrintWriter(new OutputStreamWriter(zos))
writer.println("Hello,World")
writer.flush()
// writer.close() // Closing writer closes the stream so commented it
}
}
zos.closeEntry()
zos.flush()
zos.close() // will my writer object also closed and cleaned by gc
}
Closing the ZipOutputStream
will not close the PrintWriter
nor OutputStreamWriter
; in fact, it doesn’t even know that these writers exist. The references point the other way, PrintWriter
has a reference to the OutputStreamWriter
to which it will delegate writes, flush and close operations, just as the OutputStreamWriter
will delegate to the ZipOutputStream
.
But the PrintWriter
and the OutputStreamWriter
do not bear any system resources, except for those encapsulated by the target output stream, i.e. the ZipOutputStream
. When you called flush()
to enforce writing any pending data, you did already everything needed for cleanup, as you close the ZipOutputStream
at the end.
Normally, you use the decorating stream or writer to control the lifetime, sometimes not even keeping a reference to the encapsulated stream or writer. So closing the decorating stream or writer is mandatory then.
But here, where the delegation of the close operation is not intended, you have to care to close the underlying stream. This is special, but not uncommon. This always happens when you have a file format or protocol with embedded sub formats. The ZipOutputStream
class even has a finish method dedicated to the scenario that a zip file is embedded in another stream. PrintWriter
doesn’t have such method, on the other hand, for a PrintWriter
, calling flush()
is already sufficient for finishing the operation.
Note that you should use Scala’s equivalent of try-with-resources to close the ZipOutputStream
, if there is one. Further note that you could use the same PrintWriter
throughout the entire operation, if you keep caring to flush
it at the end of each entry. That would allow to close it at the end like in simple wrapped stream scenarios.