java - 如何正确关闭嵌套的 ZipInputStreams?
问题描述
我正在使用以下代码在内存中读取嵌套的 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();
}
该代码工作正常,但我收到 StrictMode 违规错误(在 Android 中),因为嵌套流nestedZis
未正确关闭。
问题:
- 我不能更早地实例化它,因为我必须先调用
zis.getNextEntry()
才能正确定位外部流 - 我不能在 while 循环中关闭它,因为这也会关闭外部 ZipInputStream
是否有正确处理资源的解决方案?
请注意,我明确没有询问此处描述的链式流。由于上面提到的第一个问题,我不能在 try-with-resources 语句中包含嵌套流。
注意我不能使用ZipFile
,因为我只能将 Inputstream 作为我的初始资源并且无权访问文件。
解决方案
感谢@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。
推荐阅读
- html - 为什么 HTML 不允许嵌套表单?
- android - 如何将相机基本照片中的照片保存在数据库中?
- excel - 从“ThisWorkbook”问题中复制
- gitlab - Gitlab CI/CD 作业的日志超出限制
- java - 当 Junit 使用 Gradle 测试成功时自动提交 Git
- android - 如何捕获股票 Android Clock 应用程序事件?
- reactjs - 在单个组件中使用多个 redux 连接 HOC
- javascript - 未捕获的类型错误:无法在我的 php 文档上设置 null 的属性“值”
- c# - Visual Studio 自动恢复 dll 包
- outlook - Outlook 2013 将超过 n 个月的邮件移动到 pst