Java 如何使用zip4j和outputstream压缩文件夹和子文件夹

Java 如何使用zip4j和outputstream压缩文件夹和子文件夹,java,android,kotlin,zip4j,Java,Android,Kotlin,Zip4j,在我正在编写的程序中,我使用该位置的uri从用户处保存zip文件。然后,我尝试使用Android中的zip4j库和outpustream压缩文件和文件夹。我在中修改了代码,并改用zip4j。我修改过的代码生成了zip文件,但它已损坏 这是我用Kotlin编写的代码: class ZipBuilder { private fun buildZipParameters(compressionMethod: CompressionMethod, compressionLevel: Compre

在我正在编写的程序中,我使用该位置的uri从用户处保存zip文件。然后,我尝试使用Android中的zip4j库和outpustream压缩文件和文件夹。我在中修改了代码,并改用zip4j。我修改过的代码生成了zip文件,但它已损坏

这是我用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]
    }

}

如果有人能告诉我问题出在哪里,我将不胜感激。

我猜您在为特定条目写入日期后忘记了
closeEntry()
。在写入数据的while循环之后,需要执行
out.closeEntry()
。看看这个例子


谢谢,成功了。亲爱的Lingala感谢您开发和维护zip4j。。。
while (fi.read(data).also({ count = it }) != -1) {
    out.write(data, 0, count)
}
out.closeEntry() // --> close entry after writing data