不清楚你在这里问什么。
压缩到压缩
您的意思是:您想通过网络流式传输一个 zip 文件,将其保存到磁盘上的本地计算机,但只保存其中的一些文件。您想在不实际进行任何(解)压缩的情况下执行此操作。例如,如果流包含一个包含 18 个文件的 zip,您希望保存名称不以 .class 结尾的 8 个文件,但以将压缩字节直接从网络流式传输到 压缩的文件,无需任何解压缩或重新压缩。
从这个意义上说,它相当于将 zip 文件从网络保存到磁盘,然后尝试有效地清除一些条目。除了一口气。
这是一个坏主意。这里没有简单的答案。这在技术上是可行的,但有很多警告,我敢肯定你不会想要这个。
如果您需要更多关于为什么会这样的上下文,请向下滚动到此答案的末尾。
压缩到文件
如果您的意思是:“我想从网络传输一个 zip,跳过其中一些而不解压缩跳过的项目或将它们完全保存到磁盘(压缩或不压缩),并编写我想要保持直截了当的那些从网络到磁盘,即时解压缩”——这很简单。
使用.getNextEntry() 跳过。将ZipInputStream 视为单个入口流。它会 EOF 直到您移动到下一个条目,这使得它“工作”。
这是一个示例,它从 zip 文件中读取所有条目,跳过以 .class 结尾的所有条目,并将所有其他条目写入磁盘,即时解压缩:
public void unpackResources(Path zip, Path tgt) throws IOException {
try (InputStream raw = Files.newInputStream(zip)) {
ZipInputStream zip = new ZipInputStream(raw);
for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip.getNextEntry()) {
if (entry.getName().endsWith(".class")) continue;
Path to = tgt.resolve(entry.getName());
try (OutputStream out = Files.newOutputStream(to)) {
zip.transferTo(to);
}
}
}
}
in.transferTo(out) 是等效于Files.copy 的输入/输出流。 If 从 in 中读取字节并将它们直接扔到 out 中,直到 in 表示没有更多字节可提供。
上下文:为什么 zip-to-stripped-zip 不可行?
如果您完全单独处理批处理中的每个文件,压缩有时效率极低:毕竟,您无法利用文件之间的重复模式。想象一下压缩一个常见婴儿名字的数据库,其中输入数据由每个名字的 1 个文件组成,它们只包含文本 Name: Joanna,一遍又一遍。您确实需要利用那些重复的 Name: 条目来获得良好的压缩率。
如果压缩格式正确,那么您想要的就行不通了:您只有一个表(我在这里过度简化了压缩的工作原理)将较短的序列映射到较长的序列,但它是经过设计的用于有效存储整个交易。如果你去掉一半的文件,那张表可能就不再有效了。如果您不复制表格,则压缩字节没有任何意义。
一些压缩格式做错了,做完全独立处理每个文件,在“名称文件”测试中得分相当低。不幸的是,ZIP 就是这样一种格式。这确实意味着从技术上讲,将压缩数据直接流式传输到文件中/剥离一些文件可以在不解压缩/重新压缩的情况下完成,假设一个使用所有常用算法的 zip 文件(ZIP 与其说是一种算法,它是一个容器格式。然而,99% 的 zip 使用特定的算法,许多 zip 阅读器在其他 zip 上失败)。加密可能也会在这里引起问题。
考虑到这有点奇怪,通常压缩库不提供此功能;除非是针对常见的 zip 文件,否则无法做到这一点。
你必须自己写。我不确定这是否值得。解压缩和重新压缩非常快(zip 在 30 年前是可行的。在这个数字上撒上一些摩尔定律,你可能会感觉到这些天它是多么微不足道。你的磁盘将是瓶颈,而不是 CPU。即使速度很快SSD)。