从 ZipInputStream 复制条目 [英] Copying entries from ZipInputStream
问题描述
我可以像这样遍历 ZipInputStream
的 ZipEntry
s:
I am able to iterate over ZipEntry
s of a ZipInputStream
like this:
ByteArrayInputStream schema = new ByteArrayInputStream(schemaData);
ZipInputStream zis = new ZipInputStream(schema);
ZipEntry entry;
while((entry = zis.getNextEntry()) != null) {
String entryName = entry.getName();
// filter based on entry name
// how to copy this entry?
}
如何复制此 Zip 文件的某些条目?
How can I copy certain entries of this Zip file?
推荐答案
是的,这当然是可能的.当您调用 ZipInputStream.getNextEntry()
它将流定位在下一个数据条目的开始处,在这种情况下,您希望数据是子 zip 文件.流不会超过该数据的末尾,因此不必担心读入下一个条目,ZipInputStream
的条目基本上可以被视为它们自己的单个流.
Yes it is certainly possible. When you call ZipInputStream.getNextEntry()
it positions the stream at the start of the next entry of data, in this case you want the data when it's a sub zip file. The stream wont go past the end of that data so don't worry about reading into the next entry, the entries of a ZipInputStream
can essentially be treated like an individual stream of their own.
public static void main(String[] args) throws IOException {
// ** specify an output directory to copy files to
final File outDir = new File("path\\to\\...\\OutDir");
// ** read the zip input stream and do for each entry...
final String pathToZip = "path\\to\\...\\ZipTest.zip";
try (InputStream is = new FileInputStream(pathToZip);
ZipInputStream zis = new ZipInputStream(is);) {
forEachZipEntry(zis, (zipEntry, subZipStream) -> {
// ** specify how to consume each zip entry and stream...
// ** apply filters here, based on the zip entry
if (zipEntry.getName().equals("normalZippedDir.zip")) {
// ** copy the zip stream to the file
File outFile = new File(outDir, zipEntry.getName());
try (FileOutputStream fis = new FileOutputStream(outFile);) {
// apache IOUtils or whatever copy method you want
IOUtils.copy(subZipStream, fis);
} catch (IOException e) { e.printStackTrace(); }
}
});
}
}
/**
* Iterates through all {@linkplain ZipEntry}s of the given {@linkplain ZipInputStream} and
* passes the current zip entry and stream to the provided {@linkplain BiConsumer}, but does
* <b>not</b> recursively parse entries of nested zip files.
*/
public static void forEachZipEntry(ZipInputStream zis, BiConsumer<ZipEntry, ZipInputStream> consumer)
throws IOException {
Objects.requireNonNull(zis);
Objects.requireNonNull(consumer);
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
consumer.accept(entry, zis);
}
}
/**
* Recursively iterates through <b>all</b> {@linkplain ZipEntry}s <i>(including entries of nested zip
* files)</i> of the given {@linkplain ZipInputStream} passing the current zip entry and stream to
* the provided {@linkplain BiConsumer}.
*/
public static void forEachZipEntryRecursive(ZipInputStream zis,
BiConsumer<ZipEntry, ZipInputStream> consumer) throws IOException {
Objects.requireNonNull(zis);
Objects.requireNonNull(consumer);
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
consumer.accept(entry, zis);
@SuppressWarnings("resource") // ** caller shall close `zis`
ZipInputStream subZis = new ZipInputStream(zis);
forEachZipEntryRecursive(subZis, consumer);
}
}
这篇关于从 ZipInputStream 复制条目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!