Android ZipInputStream:只有 DEFLATED 条目可以有 EXT 描述符 [英] Android ZipInputStream: only DEFLATED entries can have EXT descriptor

查看:31
本文介绍了Android ZipInputStream:只有 DEFLATED 条目可以有 EXT 描述符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 android 设备上,我需要从内容 uri 中提取一个文件(一个 xapk,据我所知,这是一个普通的 zip 存档).我正在使用以下代码行创建 ZipInputStream:

On my android device, I need to extract a file (an xapk, that is a plain zip archive as far as I know) that I get from a content uri. I'm creating the ZipInputStream using this line of code:

ZipInputStream zis = new ZipInputStream(getContentResolver().openInputStream(zipUri));

然后我尝试使用以下命令读取存档的第一个条目:

And then I try to read the first entry of the archive with:

ZipEntry entry = zis.getNextEntry()

问题是我得到了这个异常:

The problem is that I get this exception:

java.util.zip.ZipException: 只有 DEFLATED 条目可以有 EXT描述符

java.util.zip.ZipException: only DEFLATED entries can have EXT descriptor

我 100% 确定存档中没有 0bytes 文件,我可以使用设备中的其他实用程序(RAR、解压缩等)提取相同的存档.

I'm 100% sure that there is no 0bytes files in the archive, and I can extract the same archive with other utilities (RAR, unzip etc) in my device.

如果我使用带有硬编码路径的 ZipFile(因此不涉及内容 uri),我可以毫无问题地提取相同的存档,因此问题与带有 uri 的 ZipInputStream 相关.另一方面,我不能在这里使用 ZipFile,因为它不支持内容 uri.

If I use a ZipFile with an hard coded path (so no content uri involved), I can extract the same archive without problems, so the issue is related to ZipInputStream with an uri. On the other hand, I can't use a ZipFile here because it doesn't support content uris.

推荐答案

不幸的是,目前唯一的答案是:

Unfortunately the only answer is currently:

不要像 ZipInputStream 那样以流模式处理 ZIP 文件.似乎所有当前可用的 ZIP 处理组件,如来自 JRE 的 ZipInputStream 和来自 Apache commons-compress 无法处理此类 ZIP 文件.

Don't process ZIP files in streaming mode like ZipInputStream does. It seems like all currently available ZIP processing components like ZipInputStream from the JRE and ZipArchiveInputStream from Apache commons-compress can not handle such ZIP files.

apache commons-compress 帮助页面上有很好的问题描述:

There is a very good description of the problem on the apache commons-compress help page:

ZIP 档案知道一个称为数据描述符的功能,这是一种方式在条目数据之后存储条目的长度.这只能工作如果可以从中央获取尺寸信息,则可靠目录或数据本身可以表明它是完整的,这是真的用于使用 DEFLATED 压缩算法压缩的数据.

ZIP archives know a feature called the data descriptor which is a way to store an entry's length after the entry's data. This can only work reliably if the size information can be taken from the central directory or the data itself can signal it is complete, which is true for data that is compressed using the DEFLATED compression algorithm.

ZipFile 可以访问中央目录并且可以提取条目可靠地使用数据描述符.同样适用于ZipArchiveInputStream 只要条目是 DEFLATED.对于存储条目 ZipArchiveInputStream 可以尝试提前读取,直到找到下一个条目,但这种方法不安全,必须由显式构造函数参数.

ZipFile has access to the central directory and can extract entries using the data descriptor reliably. The same is true for ZipArchiveInputStream as long as the entry is DEFLATED. For STORED entries ZipArchiveInputStream can try to read ahead until it finds the next entry, but this approach is not safe and has to be enabled by a constructor argument explicitly.

https://commons.apache.org/proper/commons-compress/zip.html

避免此问题的唯一方法是使用 ZipFile,但是 ZipFile 实现需要一个真实的文件,因此您可能需要保存到数据到一个临时文件.

The only possibility to avoid this problem is to use ZipFile, however the ZipFile implementation for the JRE requires a real file, therefore you may have to save to data to a temporary file.

或者如果您使用 ZipFile 来自 Apache commons-compress 并且您已经在内存中完全拥有 ZIP 文件,您可以避免使用 SeekableInMemoryByteChannel 将其保存到临时文件中.

Or if you use instead ZipFile from Apache commons-compress and you already have the ZIP file completely in-memory you can avoid saving it to a temporary file using a SeekableInMemoryByteChannel instead.

使用 Apache (Kotlin) 内存 ZipFile 的解决方案:

solution of using in-memory ZipFile of Apache (Kotlin):

ByteArrayOutputStream().use { byteArrayOutputStream ->
    inputStream.copyTo(byteArrayOutputStream)
    ZipFile(SeekableInMemoryByteChannel(byteArrayOutputStream.toByteArray())).use {
        for (entry in it.entries) {
            it.getInputStream(entry).copyTo(someOutputStream)
        }
    }
}

这篇关于Android ZipInputStream:只有 DEFLATED 条目可以有 EXT 描述符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆