如何正确地遍历 ZipInputStream 的所有条目?

How to properly iterate through all entries of a ZipInputStream?

在 Android,我正在尝试读取一个 JSON 文件,该文件包含在我的资产文件夹中的一个 zip 文件中。我 运行 遇到的问题是,当我试图获取 zipInputStream 的不存在的 nextEntry 时,它会抛出 java.io.IOException: Stream closed 异常。这是有问题的代码块:

val awesomeList: ArrayList<AwesomeItem> = arrayListOf()

BufferedInputStream(manager.open("appData.zip")).use { bufferedInputStream ->
    ZipInputStream(bufferedInputStream).use { zipInputStream ->
        var zipEntry = zipInputStream.nextEntry
        while (zipEntry != null) {
            if (zipEntry.name == "awesomeList.json") {
                JsonReader.of(Okio.buffer(Okio.source(zipInputStream))).use { reader ->
                    awesomeItems.addAll(readAwesomeArray(reader))
                }
            }
            zipEntry = zipInputStream.nextEntry
        }
    }
}

private fun readAwesomeArray(reader: JsonReader): List<AwesomeItems> {
    ...
}

使用调试器单步执行代码后,在遍历 zip 文件中的每个文件(有 4 个)后,错误在 zipEntry = zipInputStream.nextEntry 行抛出。我正在使用 Moshi 的 JsonReader 来读取 json 文件,我知道在使用断点暂停调试时检查 awesomeItems 对象是可行的。

我对 Kotlin 的 use 函数很熟悉,知道它会在完成时自动关闭一个流,但我不确定哪个流正在关闭,何时关闭,以及为什么.

我想知道使用 Kotlin 读取 zip 文件条目(从 Android 的资产文件夹)而不抛出任何异常的正确方法。网络上的大部分(如果不是全部)示例都在 Java.

请注意,use 将在函数 returns 时关闭 AutoCloseable

val input: InputStream = ...
input.use { ... }
// 'input' has been closed by this point

此外,当您打开 JsonReader 时,您正在使用 ZipInputStream 作为其来源。这意味着当 JSON reader 关闭时,ZIP 流也会关闭。这会导致您的错误,因为您在关闭 JSON reader.

后尝试处理来自 ZIP 流的更多数据

我无法保证这一点,但我相信在这种情况下您不必担心关闭 JsonReader 对象或 ZipInputStream 反对此事。持有必须及时释放的“实际”资源的对象是 manager.open(...) 返回的(我假设)InputStream。你将该流包装在一个 BufferedInputStream 中,你通过 use 关闭它,释放流持有的任何资源。这意味着您应该能够删除 useJsonReader 对象的使用,并且您的代码将正常工作(不必担心资源泄漏)。