我有一个指向虚拟文件系统(jimfs)上zip文件的路径,我需要使用ZipFile打开这个zip文件。但是ZipFile中没有以Path作为参数的构造函数,只有File。然而,我无法从我的Path创建一个File(path.toFile()),因为我会收到UnsupportedOperationException。那么我应该如何使用ZipFile打开我的zip文件呢?或者也许还有其他处理zip文件的方式,不一定在默认文件系统上进行?
ZipFile
类仅支持文件系统中的文件。
另一种选择是改用 ZipInputStream
。可以使用以下方法从您的 Path
创建一个 InputStream
:
Path path = ...
InputStream in = Files.newInputStream(path, openOptions)
使用 InputStream
创建一个 ZipInputStream
。这样应该能够正常工作:
ZipInputStream zin = new ZipInputStream(in)
try (ZipInputStream zin = new ZipInputStream(Files.newInputStream(path))) {
// do something with the ZipInputStream
}
ZipInputStream
解压某些ZIP文件会因为它们的ZIP结构而失败。这是ZIP格式的技术限制,无法解决。在这种情况下,您必须在文件系统或内存中创建一个临时文件,并使用不同的ZIP类,如ZipFile
。我刚刚解决了完全相同的问题(我需要解压缩存储在JimFS文件系统中的zip文件)。
罗伯特的回应存在问题。ZipFile
和ZipInputStream
相似,但并不相同。ZipInputStream的一个重要缺点是,如果遇到错误或损坏的zip文件,它不会失败,而是在第一次nextEntry
调用时返回null。例如,以下测试将通过而没有错误。
@Test
fun testZip() {
val randomBytes = Random.nextBytes(1000)
ZipInputStream(ByteArrayInputStream(randomBytes)).use { zis ->
var zipEntry = zis.nextEntry
while (zipEntry != null) {
println(zipEntry.name)
zipEntry = zis.nextEntry
}
}
}
ZipInputStream
检查zip文件时没有任何机会。唯一的选择是使用Java的FileSystems
。以下测试将失败,并显示错误 zip END header not found 。当然,使用正确的zip文件,newFileSystem可以正常工作。
@Test
fun testZipFS() {
val randomBytes = Random.nextBytes(1000)
val tmpFile = Files.createTempFile(Path.of("/tmp"), "tmp", ".zip")
Files.write(tmpFile, randomBytes)
val zipFs = FileSystems.newFileSystem(srcZip, null)
val zipRoot = zipFs.rootDirectories.single()
Files.walk(zipRoot).forEach { p ->
println(p.absolutePathString())
}
}
ZipFile(String)
替代? - Yassin HajajFileNotFoundException
,因为它在默认文件系统上找到了该文件,但在虚拟文件系统上没有找到。 - Pavel_K