如何正确关闭嵌套的 ZipInputStreams?

How to correctly close nested 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();
}

代码工作正常,但由于嵌套流 nestedZis 未正确关闭,我收到 StrictMode 违规错误(在 Android 中)。

问题:

  1. 我无法提前实例化它,因为我必须先调用 zis.getNextEntry() 才能正确定位外部流
  2. 我无法在 while 循环中关闭它,因为那样也会关闭外部 ZipInputStream

是否有正确处理资源的解决方案?

注意 我明确地没有询问 here 中描述的链式流。由于上面提到的第一个问题,我无法在 try-with-resources 语句中包含嵌套流。

注意我不能使用ZipFile因为我只能得到一个输入流作为我的初始资源并且不能访问文件。

感谢@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。