首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >读Kotlin中的ZipInputStream

读Kotlin中的ZipInputStream
EN

Stack Overflow用户
提问于 2018-09-12 14:24:13
回答 3查看 3.6K关注 0票数 6

我正在尝试使用Kotlin和ZipInputStream将压缩后的文件读入ByteArrayOutputStream()

代码语言:javascript
复制
val f = File("/path/to/zip/myFile.zip")
val zis = ZipInputStream(FileInputStream(f))

//loop through all entries in the zipped file
var entry = zis.nextEntry
while(entry != null) {
    val baos = ByteArrayOutputStream()

    //read the entry into a ByteArrayOutputStream
    zis.use{ it.copyTo(baos) }

    val bytes = baos.toByteArray()

    System.out.println(bytes[0])

    zis.closeEntry()  //error thrown here on first iteration
    entry = zis.nextEntry
}

我得到的错误是:

代码语言:javascript
复制
java.io.IOException: Stream closed
    at java.util.zip.ZipInputStream.ensureOpen(ZipInputStream.java:67)
    at java.util.zip.ZipInputStream.closeEntry(ZipInputStream.java:139)
    <the code above>

我以为在读取条目内容之后,zis.use可能已经关闭了条目,所以我删除了zis.closeEntry(),但是当尝试获取下一个条目时,它产生了相同的错误。

我知道zis.use是安全的,并且保证输入流是关闭的,但我希望它只关闭条目(如果有的话),而不是关闭整个流。

打印完整个字节数组后,我知道在zis.use期间只读取zip中的第一个文件

是否有一种很好的方法来读取kotlin中的ZipInputStream中的所有条目?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-09-12 14:33:18

use函数调用关闭整个流的关闭()方法,而不是只关闭当前条目的closeEntry()。我认为您应该用zis.use { ... }包装整个zis.use { ... }循环,而不是为每个条目调用它。

票数 3
EN

Stack Overflow用户

发布于 2021-03-18 01:22:23

是否有一种很好的方法来读取kotlin中的ZipInputStream中的所有条目?

下面是一个从Zip文件中提取文件的函数,您可以使用它作为基础,并根据自己的需要进行调整:

代码语言:javascript
复制
data class UnzippedFile(val filename: String, val content: ByteArray)

fun unzip(file: File): List<UnzippedFile> = ZipInputStream(FileInputStream(file))
    .use { zipInputStream ->
        generateSequence { zipInputStream.nextEntry }
            .filterNot { it.isDirectory }
            .map {
                UnzippedFile(
                    filename = it.name,
                    content = zipInputStream.readAllBytes()
                )
            }.toList()
    }

关键是使用generateSequence来处理对条目的迭代,直到没有剩下的条目。

示例用法,提取包含目录中三个文本文件的zip:

代码语言:javascript
复制
fun main() {
    val unzipped = unzip(File("zipped.zip"))
    for ((filename, content) in unzipped) {
        println("Contents of $filename: '${content.toString(Charset.defaultCharset()).trim()}'")
    }
}

输出:

代码语言:javascript
复制
Contents of zipped/two.txt: 'contents of two'
Contents of zipped/three.txt: 'three!!!!'
Contents of zipped/one.txt: 'contents of one'
票数 11
EN

Stack Overflow用户

发布于 2018-09-12 14:34:59

在Kotlin中,use将关闭实现AutoCloseable的资源。这意味着它的close()方法将自动为您调用。我认为您假设在ZipInputStream中,这已经被重写为只关闭条目,但它没有。

根据文献资料

关闭此输入流并释放与流相关联的任何系统资源。重点雷

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52297482

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档