scala - 当我关闭 zipoutputstream 时,与之关联的写入器对象是否也会被 GC 关闭和清理
问题描述
尝试创建一个包含 3 个文件的 ZIP 文件。我正在使用 ZipOutputStream 创建 ZIP 文件,使用 Printwriter 创建文件并将其写入 Zip。
当我在写入文件后关闭 printwriter 对象时也会关闭流,我知道。但是,如果我在写入 zip 后关闭 zip 输出流,它也会关闭并清理我的打印机对象
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
nor OutputStreamWriter
;事实上,它甚至不知道这些作家的存在。引用指向另一种方式,PrintWriter
具有对OutputStreamWriter
将委托写入、刷新和关闭操作的 的引用,就像OutputStreamWriter
将委托给ZipOutputStream
.
但是PrintWriter
和OutputStreamWriter
不承担任何系统资源,除了那些被目标输出流封装的资源,即ZipOutputStream
. 当您调用flush()
强制写入任何未决数据时,您已经完成了清理所需的一切,因为您ZipOutputStream
最后关闭了。
通常,您使用装饰流或编写器来控制生命周期,有时甚至不保留对封装流或编写器的引用。所以关闭装饰流或作家是强制性的。
但是在这里,如果不打算委托关闭操作,则必须注意关闭底层流。这很特殊,但并不少见。当您拥有带有嵌入子格式的文件格式或协议时,总是会发生这种情况。该类ZipOutputStream
甚至有一个完成方法,专用于将 zip 文件嵌入到另一个流中的场景。PrintWriter
另一方面,没有这样的方法,对于 a PrintWriter
,调用flush()
已经足够完成操作了。
请注意,您应该使用 Scala 等效的try-with-resources来关闭ZipOutputStream
,如果有的话。进一步注意,如果您在每个条目的末尾PrintWriter
继续关注它,您可以在整个操作中使用相同的。flush
这将允许在最后关闭它,就像在简单的包装流场景中一样。
推荐阅读
- rx-java - RxJava:调度程序使用比预期更多的线程
- python - 创建带引号的字符串
- javascript - 使用参数 id 反应路由器路由
- javascript - 无法覆盖嵌套 Material UI 组件的样式
- python - 如何获取 pytest 依赖项的返回/收益值
- python - Flask 正在接收 GET 请求而不是 POST
- yaml - 如何从 ymal 中的特定分支获取管道运行详细信息
- javascript - 在 React 状态下更新对象数据成员不会触发重新渲染
- html - 使用 css 和 HTML 的 streamlabs OBS 的简单文本擦除效果
- sparql - 如何使用 SPARQL 查询 Wikidata 以获取特定属性?