Search code examples
kotlinrecursionunzip

Extracting a Zip archive containing nested zip files using Kotlin


I'm working on an application that needs to extract a zip archive of json documents into a folder. The problem I'm encountering is that sometimes the archive contains nested zip files. My current code looks like this:

fun File.unzipServiceFile(toPath: String): List<File>
    {
        val retFiles = mutableListOf<File>()
        ZipFile(this).use { zipFile ->
            zipFile.entries().asSequence().forEach { zipEntry ->
                zipFile.getInputStream(zipEntry).use { input ->
                    //if there are nested zip files, we need to extract them
                    if (zipEntry.name.endsWith(".zip")) {
                        //we need to go deeper
                    }
                    else if (zipEntry.name.endsWith(".json") && !zipEntry.isDirectory && !zipEntry.name.startsWith(".") && !zipEntry.name.startsWith(
                            "_"
                        )
                    ) {
                        val file = File("$toPath/${zipEntry.name}")
                        FileUtils.writeByteArrayToFile(file, input.readBytes())
                        retFiles.add(file)
                    }
                }
            }
        }

        return retFiles
    }

I don't actually want to write the nested zip files to a folder since I would then have to clean them out of the directory. I simply want to extract the contents, or continue recursing if there are additional layers of nesting. Any idea how I could go about doing this?


Solution

  • You can unzip a File by using a ZipFile instance, but you can also unzip the contents of an InputStream by using an instance of ZipInputStream:

    zipFile.getInputStream(zipEntry).use { input ->
        //if there are nested zip files, we need to extract them
        if (zipEntry.name.endsWith(".zip")) {
            ZipInputStream(input).use { zipStream ->
                val nestedZipEntry: ZipEntry = zipStream.nextEntry
                // ...
            }
        } else if ...
    }
    

    See here if you need additional help unzipping from a ZipInputStream: How to read file from ZIP using InputStream?