1. Introduction

Creating a ZIP file is a common task when we need to compress files or directories. Because ZIP files are grouped and compressed, they are easier to store and transfer than uncompressed files. Consequently, Kotlin provides multiple ways to achieve this.

In this tutorial, we’ll investigate various methods to create a ZIP file using Kotlin, including standard Java libraries and other third-party libraries.

2. Using the java.util.zip Package

First, we can use the java.util.zip package to create a ZIP file in Kotlin. This package is part of the standard Java library and provides classes for reading and writing ZIP files:

fun createZipFile(files: List<File>, outputZipFile: File): File {
    ZipOutputStream(FileOutputStream(outputZipFile)).use { zipOut ->
        files.forEach { file ->
            FileInputStream(file).use { fis ->
                val zipEntry = ZipEntry(file.name)
                zipOut.putNextEntry(zipEntry)
                fis.copyTo(zipOut)
                zipOut.closeEntry()
            }
        }
    }
    return outputZipFile
}

This function needs an output stream and several input streams when reading the list of files and while writing them to the ZIP file.

First, we open a ZipOutputStream, which needs a FileOutputStream on the File reference for our ZIP file.

Within the ZipOutputStream, we open a FileInputStream for each file we’re copying to the ZIP file. We create a ZipEntry with information about the file, and then use copyTo() to put the file in the ZIP file. We then use closeEntry() to finish adding a file to the ZIP file. Notice that these file operations are wrapped in use() to close the file automatically when we finish.

Let’s test that our function creates a ZIP file. Before our test, let’s make a list of files to ZIP file:

val filesToZip = listOf(File("file1.txt").apply { writeText("Hello, World!") }, File("file2.txt").apply { writeText("Kotlin ZIP Test") })
@Test
fun `create  zip file with java standard library`() {
    val outputZipFile = createZipFile(filesToZip, File("test_output.zip"))

    assertTrue(outputZipFile.exists())
    assertTrue(outputZipFile.length() > 0)

    filesToZip.forEach { it.delete() }
    outputZipFile.delete()
}

This test shows the successful creation of a ZIP file using our createZipFile() method. We verify the ZIP file exists and is not empty. Finally, to clean up, we delete all files associated with the test.

3. Using Apache Commons Compress

Apache Commons Compress is a third-party library that offers greater flexibility and supplementary features for handling ZIP files in comparison to the standard Java library that we examined in the previous approach:

fun createZipFileWithApache(files: List<File>, outputZipFile: File): File {
    ZipArchiveOutputStream(outputZipFile).use { zipOut ->
        files.forEach { file ->
            FileInputStream(file).use { fis ->
                IOUtils.copy(fis, zipOut)
            }
        zipOut.closeArchiveEntry()
        }
    }

    return outputZipFile
}

The ZipArchiveOutputStream simplifies the ZIP file process by consolidating the output stream for the ZIP. Likewise, within the ZipArchiveOutStream, we take a similar approach of reading each file and copying it to the final ZIP file with IOUtils.copy().

Again, let’s test our helper function to confirm that the ZIP file exists and is not empty:

@Test
fun `create zip file with apache commons compress`() {
    val outputZipFile = createZipFileWithApache(filesToZip, File("test_output_with_apache.zip"))

    assertTrue(outputZipFile.exists())
    assertTrue(outputZipFile.length() > 0)

    filesToZip.forEach { it.delete() }
    outputZipFile.delete()
}

Apache Commons Compress is similar to the standard Java library’s offering for working with ZIP files but offers more robust features. The ZipArchiveOutputStream and ZipArchiveEntry classes provide a simpler API for handling ZIP files.

4. Using Zip4j

Finally, we can also leverage the Zip4j library to create a ZIP file. Zip4j is a popular library for working with ZIP files in Java, and it provides an easy-to-use API. This library provides additional features such as password protection and AES encryption.

4.1. Dependency

First, we need to add the dependency to our project.

For Maven, let’s add this dependency to our pom.xml file:

<dependency>
    <groupId>net.lingala.zip4j</groupId>
    <artifactId>zip4j</artifactId>
    <version>2.8.0</version>
</dependency>

For Gradle, we need to add this dependency to the build.gradle file:

dependencies {
    implementation("net.lingala.zip4j:zip4j:2.8.0")
}

4.2. Creating a ZIP File With Zip4j

Now, let’s write a function that uses the Zip4j library to create a ZIP file:

fun createZipFileWithZip4j(files: List<File>, outputZipFile: File): File {
    val zipFile = ZipFile(outputZipFile)
    val parameters = ZipParameters().apply {
        compressionMethod = CompressionMethod.DEFLATE
        compressionLevel = CompressionLevel.NORMAL
    }
    zipFile.addFiles(files, parameters)

    return outputZipFile
}

Specifically, we initialize a ZipFile object with the output file and set up ZipParameters for compression. Then, we directly add the files we want to include in our zipFile with addFiles(). This method handles opening and writing the files to the ZIP file without us needing to deal with any input or output streams this time.

As always, let’s confirm that we’re able to create a ZIP file with Zip4j:

@Test
fun `create zip file with Zip4j library`() {
    val outputZipFile = File("test_output_with_zip4j.zip")

    createZipFileWithZip4j(filesToZip, outputZipFile)

    assertTrue(outputZipFile.exists())
    assertTrue(outputZipFile.length() > 0)

    filesToZip.forEach { it.delete() }
    outputZipFile.delete()
}

5. Conclusion

In this article, we’ve explored various ways of creating a ZIP file in Kotlin. First, we explored the standard java.util.zip package. Next, we saw how to use the Apache Commons Compress library to create a ZIP file. Finally, we leveraged the Zip4j library to demonstrate its simple API for creating a ZIP file.

As always, the code for these examples is available over on GitHub.