How to zip folder and sub-folder using zip4j and outputstream Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of How to zip folder and sub-folder using zip4j and outputstream without wasting too much if your time.

The question is published on by Tutorial Guruji team.

In the program that I am writing, I take the uri of the location to save the zip file from a user. Then, I try to zip the files and folders using zip4j library and outpustream in Android. I modified the code in this Stackoverflow answer and used zip4j instead. My modified code produces the zip file, however it is corrupted.

this is my code written in Kotlin:

class ZipBuilder {
    private fun buildZipParameters(compressionMethod: CompressionMethod, compressionLevel: CompressionLevel,
                                   encrypt: Boolean,
                                   encryptionMethod: EncryptionMethod?,
                                   aesKeyStrength: AesKeyStrength?
    ): ZipParameters? {
        val zipParameters = ZipParameters()
        zipParameters.compressionMethod = compressionMethod
        zipParameters.compressionLevel = compressionLevel
        return zipParameters
    }


    fun zipFileAtPath(sourcePath: String?, toLocation: ParcelFileDescriptor?): Boolean {
        println("zipFileAtPath is called")
        val BUFFER = 2048
        val sourceFile = File(sourcePath!!)
        val zipParameters = buildZipParameters(CompressionMethod.DEFLATE, CompressionLevel.NORMAL,
            false, null, null)

        try {
            var origin: BufferedInputStream? = null
            val desc = toLocation
            val dest = FileOutputStream(desc!!.fileDescriptor)
            val out = ZipOutputStream(BufferedOutputStream(dest)) 

            if (sourceFile.isDirectory) {
                zipParameters.rootFolderNameInZip = sourcePath
                zipSubFolder(out, sourceFile, sourceFile.parent!!.length, zipParameters!!)
            } else {
                val data = ByteArray(BUFFER)
                val fi = FileInputStream(sourcePath)
                origin = BufferedInputStream(fi, BUFFER)

                zipParameters!!.fileNameInZip = getLastPathComponent(sourcePath)
                zipParameters.lastModifiedFileTime = sourceFile.lastModified()

                out.putNextEntry(zipParameters)

                var count: Int = 0
                while (fi.read(data).also({ count = it }) != -1) {
                    out.write(data, 0, count)
                }
            }
            out.close()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            return false
        }
        return true
    }

    @Throws(IOException::class)
    private fun zipSubFolder(
        out: ZipOutputStream, folder: File, basePathLength: Int, zipParameters: ZipParameters
    ) {
        val BUFFER = 2048
        val fileList = folder.listFiles()
        var origin: BufferedInputStream
        fileList?.forEach { file ->
            if (file.isDirectory) {
                zipSubFolder(out, file, basePathLength, zipParameters)
            } else {
                val data = ByteArray(BUFFER)
                val unmodifiedFilePath = file.path
                val relativePath = unmodifiedFilePath
                    .substring(basePathLength)
                val fi = FileInputStream(unmodifiedFilePath)
                origin = BufferedInputStream(fi, BUFFER)


                zipParameters.fileNameInZip = relativePath
                zipParameters.lastModifiedFileTime = file.lastModified()
                out.putNextEntry(zipParameters)


                var count: Int = 0

                while (fi.read(data).also({ count = it }) != -1) {
                    out.write(data, 0, count)
                }
                origin.close()
            }
        }
    }

    fun getLastPathComponent(filePath: String): String? {
        val segments = filePath.split("/").toTypedArray()
        return if (segments.size == 0) "" else segments[segments.size - 1]
    }

}

I would appreciate it if someone could tell me what could be the problem.

Answer

I guess you forgot to closeEntry() after writing date for that particular entry. You need to do out.closeEntry() after the while loop of writing data. Have a look at the example here.

while (fi.read(data).also({ count = it }) != -1) {
    out.write(data, 0, count)
}
out.closeEntry() // --> close entry after writing data

We are here to answer your question about How to zip folder and sub-folder using zip4j and outputstream - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji