当我关闭 zipoutputstream 时,与其关联的 writer 对象是否也会被 GC 关闭和清理
When i close the zipoutputstream does the writer objects associated with it will also be closed and cleaned by GC
正在尝试创建一个包含 3 个文件的 ZIP 文件。我正在使用 ZipOutputStream 创建 ZIP 文件,使用 Printwriter 创建文件并将文件写入 Zip。
当我在写入文件后关闭 printwriter 对象时,流也会关闭,我知道这一点。但是如果我在写入 zip 后关闭 zip 输出流,它也会关闭并清理我的 printwriter 对象
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
}
关闭 ZipOutputStream
不会关闭 PrintWriter
也不会关闭 OutputStreamWriter
;事实上,它甚至不知道这些作家的存在。引用指向另一个方向,PrintWriter
有一个对 OutputStreamWriter
的引用,它将委托写入、刷新和关闭操作,就像 OutputStreamWriter
将委托给 ZipOutputStream
.
但是PrintWriter
和OutputStreamWriter
不承载任何系统资源,除了那些被目标输出流封装的,即ZipOutputStream
。当您调用 flush()
强制写入任何未决数据时,您已经完成了清理所需的一切,因为您最后关闭了 ZipOutputStream
。
通常,您使用装饰流或编写器来控制生命周期,有时甚至不保留对封装流或编写器的引用。所以关闭装饰流或编写器是强制性的。
但是在这里,关闭操作的授权不是预期的,你必须注意关闭底层流。这很特别,但并不少见。当您拥有包含嵌入式子格式的文件格式或协议时,这总是会发生。 ZipOutputStream
class 甚至还有一个 finish method 专用于将 zip 文件嵌入到另一个流中的场景。 PrintWriter
没有这样的方法,另一方面,对于PrintWriter
,调用flush()
已经足以完成操作。
请注意,您应该使用 Scala 的等效 try-with-resources 来关闭 ZipOutputStream
,如果有的话。进一步请注意,您可以在整个操作过程中使用相同的 PrintWriter
,如果您在每个条目的末尾继续关注 flush
。这将允许在最后关闭它,就像在简单的包装流场景中一样。
正在尝试创建一个包含 3 个文件的 ZIP 文件。我正在使用 ZipOutputStream 创建 ZIP 文件,使用 Printwriter 创建文件并将文件写入 Zip。
当我在写入文件后关闭 printwriter 对象时,流也会关闭,我知道这一点。但是如果我在写入 zip 后关闭 zip 输出流,它也会关闭并清理我的 printwriter 对象
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
}
关闭 ZipOutputStream
不会关闭 PrintWriter
也不会关闭 OutputStreamWriter
;事实上,它甚至不知道这些作家的存在。引用指向另一个方向,PrintWriter
有一个对 OutputStreamWriter
的引用,它将委托写入、刷新和关闭操作,就像 OutputStreamWriter
将委托给 ZipOutputStream
.
但是PrintWriter
和OutputStreamWriter
不承载任何系统资源,除了那些被目标输出流封装的,即ZipOutputStream
。当您调用 flush()
强制写入任何未决数据时,您已经完成了清理所需的一切,因为您最后关闭了 ZipOutputStream
。
通常,您使用装饰流或编写器来控制生命周期,有时甚至不保留对封装流或编写器的引用。所以关闭装饰流或编写器是强制性的。
但是在这里,关闭操作的授权不是预期的,你必须注意关闭底层流。这很特别,但并不少见。当您拥有包含嵌入式子格式的文件格式或协议时,这总是会发生。 ZipOutputStream
class 甚至还有一个 finish method 专用于将 zip 文件嵌入到另一个流中的场景。 PrintWriter
没有这样的方法,另一方面,对于PrintWriter
,调用flush()
已经足以完成操作。
请注意,您应该使用 Scala 的等效 try-with-resources 来关闭 ZipOutputStream
,如果有的话。进一步请注意,您可以在整个操作过程中使用相同的 PrintWriter
,如果您在每个条目的末尾继续关注 flush
。这将允许在最后关闭它,就像在简单的包装流场景中一样。