Created
October 19, 2017 19:44
-
-
Save kevinmilner/662edff1fadcd99de015c8de1294caa1 to your computer and use it in GitHub Desktop.
Efficiently copy a zip entry from one archive to another in java without decompressing/compressing with Apache Commons Compress
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.File; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.util.Enumeration; | |
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; | |
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; | |
import org.apache.commons.compress.archivers.zip.ZipFile; | |
public class ZipEntryCopy { | |
public static void main(String[] args) throws IOException { | |
File zipIn = new File("/tmp/input.zip"); | |
File zipOut = new File("/tmp/output.zip"); | |
ZipFile zip = new ZipFile(zipIn); | |
ZipArchiveOutputStream out = new ZipArchiveOutputStream(new FileOutputStream(zipOut)); | |
Enumeration<? extends ZipArchiveEntry> entries = zip.getEntries(); | |
while (entries.hasMoreElements()) { | |
ZipArchiveEntry e = entries.nextElement(); | |
// I needed to be able to change the name. if you don't, | |
// you can skip this block and just use 'e' as 'outEntry' | |
ZipArchiveEntry outEntry = new ZipArchiveEntry("test_"+e.getName()); | |
outEntry.setCompressedSize(e.getCompressedSize()); | |
outEntry.setCrc(e.getCrc()); | |
outEntry.setExternalAttributes(e.getExternalAttributes()); | |
outEntry.setExtra(e.getExtra()); | |
outEntry.setExtraFields(e.getExtraFields()); | |
outEntry.setGeneralPurposeBit(e.getGeneralPurposeBit()); | |
outEntry.setInternalAttributes(e.getInternalAttributes()); | |
outEntry.setMethod(e.getMethod()); | |
outEntry.setRawFlag(e.getRawFlag()); | |
outEntry.setSize(e.getSize()); | |
out.addRawArchiveEntry(outEntry, zip.getRawInputStream(e)); | |
} | |
zip.close(); | |
out.close(); | |
} | |
} |
This is exactly what I was looking for. Thank you for having this up!
Instead of decompressing and recompressing every entry just to modify a couple of entries in a zip, we can copy over all of the entries we don't need to modify, making a 400MB compressed file take 1.5 seconds to process rather than 55+ seconds.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If you try to do this with the standard Java Zip libraries, you will have to decompress (inflate) each entry just to immediately recompress (deflate) it. This is very wasteful. In my tests, this method is an ~8x speedup.