Zip and Unzip Files in Java
In this tutorial, we’ll learn how to zip a file or directory into an archive and how to unzip the archive into a directory using Java core libraries.
Zip a File
Let’s look at the example where we want to zip a single file into an archive:-
public static void zipFile(Path fileToZip, Path zipFile) throws IOException {
Files.createDirectories(zipFile.getParent());
try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(zipFile))) {
ZipEntry zipEntry = new ZipEntry(fileToZip.toFile().getName());
zipOutputStream.putNextEntry(zipEntry);
if (Files.isRegularFile(fileToZip)) {
Files.copy(fileToZip, zipOutputStream);
}
}
}
The below method call will zip a file /cnc/toZip/picture1.png
into an archive /cnc/zip/singleFileArchive.zip
:-
zipFile(Path.of("/cnc/toZip/picture1.png"), Path.of("/cnc/zip/singleFileArchive.zip"));
Make note of following in this method:-
- Using Java nio method
Files.createDirectories()
to create all directories of zip file if doesn’t exist. Unlike theFiles.createDirectory()
method, an exception is not thrown if it already exists. - Initializing the
ZipOutputStream
in thetry
block so that closing the streams will be taken care by JVM. - Using Java nio method
Files.copy()
to copy the file toZipOutputStream
, makes your code concise.
Zip Multiple files
Let’s look at the example where we want to zip multiple files into an archive:-
public static void zipMultipleFiles(List<Path> filesToZip, Path zipFile) throws IOException {
Files.createDirectories(zipFile.getParent());
try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(zipFile))) {
for(Path fileToZip: filesToZip){
ZipEntry zipEntry = new ZipEntry(fileToZip.toFile().getName());
zipOutputStream.putNextEntry(zipEntry);
if (Files.isRegularFile(fileToZip)) {
Files.copy(fileToZip, zipOutputStream);
}
}
}
}
The below method call will zip these two files picture1.png
& picture2.png
into an archive /cnc/zip/multiFileArchive.zip
:-
List<Path> filesToZip = Arrays.asList(Path.of("/cnc/toZip/picture1.png"), Path.of("/cnc/toZip/picture2.png"));
zipMultipleFiles(filesToZip, Path.of("/cnc/zip/multiFileArchive.zip"));
Make note that we put each file entry in ZipEntry
which represents the archive file.
Zip All Files and Folders in a Directory
Let’s look at the example where we want to zip all the files and folders inside a directory into an archive:-
public static void zipDirectory(Path directoryToZip, Path zipFile) throws IOException {
Files.deleteIfExists(zipFile);
Files.createDirectories(zipFile.getParent());
try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(zipFile))) {
if (Files.isDirectory(directoryToZip)) {
Files.walk(directoryToZip).filter(path -> !Files.isDirectory(path)).forEach(path -> {
ZipEntry zipEntry = new ZipEntry(directoryToZip.relativize(path).toString());
try {
zipOutputStream.putNextEntry(zipEntry);
if (Files.isRegularFile(path)) {
Files.copy(path, zipOutputStream);
}
zipOutputStream.closeEntry();
} catch (IOException e) {
System.err.println(e);
}
});
}
}
}
The below method call will zip all the files and folders inside /cnc/toZip
recursively into an archive /cnc/zip/fullDirectoryArchive.zip
:-
zipDirectory(Path.of("/cnc/toZip"), Path.of("/cnc/zip/fullDirectoryArchive.zip"));
Make note of following in this method:-
- Using Java NIO file utility methods
Files.deleteIfExists()
andFiles.createDirectories()
, which are safe to use and doesn’t throw an exception if file or directory doesn’t exist. - Initializing the
ZipOutputStream
in thetry
block so that closing the streams will be taken care by JVM. - Using Java NIO
Files.walk()
to iterate through all files and folders recursively in a directory using Java Streams. - Put each file or directory entry in the
ZipEntry
, which represents the archive file.
Unzip an Archive file
Let’s look at the example where we want to unzip an archive file into target directory:-
public static void unzipDirectory(Path zipFile, Path targetDirectory) throws IOException {
if (!Files.exists(zipFile)) {
return;
}
deleteDirectoryRecursively(targetDirectory);
Files.createDirectory(targetDirectory);
try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(zipFile))) {
ZipEntry entry;
while ((entry = zipInputStream.getNextEntry()) != null) {
final Path toPath = targetDirectory.resolve(entry.getName());
if (entry.isDirectory()) {
Files.createDirectory(toPath);
} else {
if (!Files.exists(toPath.getParent())) {
Files.createDirectories(toPath.getParent());
}
Files.copy(zipInputStream, toPath);
}
}
}
}
private static void deleteDirectoryRecursively(Path dir) throws IOException {
if (Files.exists(dir)) {
Files.walk(dir).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
}
}
The below method call will unzip all the files and folders inside fullDirectoryArchive.zip
recursively into the directory /cnc/toUnzip
:-
unzipDirectory(Path.of("/cnc/zip/fullDirectoryArchive.zip"), Path.of("/cnc/toUnzip"));
Make note of following in this method:-
- Doing initial validations for e.g. return and do nothing if zip file does’nt exist, delete the target directory recursively if it already exist.
- Initializing the
ZipInputStream
in thetry
block so that closing the streams will be taken care by JVM. - Iterate through
ZipEntry
, which is an archive file representation and have all archive information:-
- If it is a directory then create that directory
- If it is a file then create all its parent directories and then copy that file
Thats it for this tutorial. Thanks for reading and happy learning!
Download the ZipFileUtil.java which have all these methods and start using in your code.