Java provides support for reading zip files in the form of ZipInputStream
. This class provides an API where you can
iterate over all the items in a given zip file, reading the data from the archive for each file.
In order to do this, first you must create the ZipInputStream
instance giving the file that you wish to
expand. Then you iterate using the getNextEntry
method on the stream, which returns the header data for
each entry in turn. Importantly this does not contain the data, which is actually read from the stream separately.
In order to execute the example below, you need to provide two parameters, firstly the zip file that is to be processed, and secondly the output directory where the uncompressed files are to be stored.
package com.thecoderscorner.example.compression;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* ZipReader reads the zip file specified using ZipInputStream,
* it then outputs the raw files into the output directory
* specified as a parameter.
*/
public class ZipReader
{
private static final Logger LOGGER = Logger.getLogger("ZipReader");
// Expands the zip file passed as argument 1, into the
// directory provided in argument 2
public static void main(String args[]) throws Exception
{
if(args.length != 2)
{
LOGGER.severe("zipreader zipfile outputdir");
return;
}
// create a buffer to improve copy performance later.
byte[] buffer = new byte[2048];
Path outDir = Paths.get(args[1]);
try(
// we open the zip file using a java 7 try with resources block so
// that we don't need a finally.
ZipInputStream stream = new ZipInputStream(new FileInputStream(args[0]))
)
{
LOGGER.info("Zip file: " + args[0] + " has been opened");
// now iterate through each file in the zip archive. The get
// next entry call will return a ZipEntry for each file in
// the stream
ZipEntry entry;
while((entry = stream.getNextEntry())!=null)
{
// We can read the file information from the ZipEntry.
String fileInfo = String.format("Entry: [%s] len %d added %TD",
entry.getName(), entry.getSize(),
new Date(entry.getTime()));
LOGGER.info(fileInfo);
Path filePath = outDir.resolve(entry.getName());
// Now we can read the file data from the stream. We now
// treat the stream like a usual input stream reading from
// it until it returns 0 or less.
try (
FileOutputStream output = new FileOutputStream(filePath.toFile())
)
{
LOGGER.info("Writing file: " + filePath);
int len;
while ((len = stream.read(buffer)) > 0)
{
output.write(buffer, 0, len);
}
}
}
}
}
}
and to standard out
Mar 28, 2017 7:36:43 PM com.thecoderscorner.example.compression.ZipReader main
INFO: Zip file: c:/dev/temp/transistor.zip has been opened
Mar 28, 2017 7:36:43 PM com.thecoderscorner.example.compression.ZipReader main
INFO: Entry: [transistor.jpg] len 2329 added 05/02/15
Mar 28, 2017 7:36:43 PM com.thecoderscorner.example.compression.ZipReader main
INFO: Writing file: c:\dev\temp\zipout\transistor.jpg
Process finished with exit code 0
and in the output directory specified on the command line
dave@DAVESLAPTOP:/mnt/c/Dev/temp/zipout$ ls -l
total 4
-rwxrwxrwx 1 root root 2329 Mar 28 19:36 transistor.jpg
We opened a zip file as a stream, and then we iterated over the files contained in the zip file. For each file entry found we output some of its characteristics and then saved the file to disk. Note that we read the file from the same stream object that we retrieved the ZipEntry.
Follow on to another article that combines this with Java 8 filtering. Filtered extraction from zip file using ZipInputStream and Java 8