如何正确关闭嵌套的 ZipInputStreams?
Posted
技术标签:
【中文标题】如何正确关闭嵌套的 ZipInputStreams?【英文标题】:How to correctly close nested ZipInputStreams? 【发布时间】:2021-07-27 11:58:58 【问题描述】:我正在使用以下代码读取一个嵌套的 zip 文件(一个包含多个其他 zip 文件的 zip 文件)在内存中
try (ZipInputStream zis = new ZipInputStream(inputStream))
ZipEntry zipEntry;
while ((zipEntry = zis.getNextEntry()) != null)
if (zipEntry.getName().endsWith(".zip"))
ZipInputStream nestedZis = new ZipInputStream(zis);
Pojo myPojo = myPojoReader.readFrom(nestedZis);
zis.closeEntry();
代码运行良好,但由于嵌套流 nestedZis
未正确关闭,因此出现 StrictMode 违规错误(在 android 中)。
问题:
-
我无法提前实例化它,因为我必须先调用
zis.getNextEntry()
才能正确定位外部流
我无法在 while 循环中关闭它,因为这也会关闭外部 ZipInputStream
是否有正确处理资源的解决方案?
注意我明确没有询问here 所述的链式流。由于上面提到的第一个问题,我不能在 try-with-resources 语句中包含嵌套流。
注意我不能使用ZipFile
,因为我只能获取一个输入流作为我的初始资源并且无权访问文件。
【问题讨论】:
你需要把zip.closeEntry()
放在while循环里面。
这不会改变任何事情,因为getNextEntry()
在内部调用closeEntry()
。
你是对的。 Apache 的 CloseShieldInputStream 有帮助吗?
确实如此!谢谢你的提示。您想将此添加为答案以便我接受吗?
我很高兴我的想法有所帮助,但我对 StrictMode 不熟悉,所以我将把它留给别人(可能是你自己)写一个好的答案。
【参考方案1】:
感谢 @k314159 提供的使用 Apache 的 CloseShieldInputStream
的提示,它是 Apache Commons IO 库的一部分,我将代码更改为:
try (ZipInputStream zis = new ZipInputStream(inputStream))
ZipEntry zipEntry;
while ((zipEntry = zis.getNextEntry()) != null)
if (zipEntry.getName().endsWith(".zip"))
try (CloseShieldInputStream cloned = CloseShieldInputStream.wrap(zis); ZipInputStream nestedZis = new ZipInputStream(cloned))
Pojo myPojo = myPojoReader.readFrom(nestedZis);
zis.closeEntry();
这保留了我的代码的功能,同时还通过了 Android 的 StrictMode 验证。
CloseShieldInputStream
是一个代理流,可防止底层输入流被关闭。
注意还有一个CloseShieldOutputStream
,我现在用它来生成嵌套的 zip。
【讨论】:
以上是关于如何正确关闭嵌套的 ZipInputStreams?的主要内容,如果未能解决你的问题,请参考以下文章
具有自定义数据结构的 SwiftUI 列表,每个循环都嵌套 [关闭]