1

私が書いているプログラムでは、zip ファイルを保存する場所の uri をユーザーから受け取ります。次に、zip4j ライブラリと Android の outpustream を使用して、ファイルとフォルダーを圧縮しようとします。この Stackoverflow の回答のコードを変更し、 代わりに 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]
    }

}

何が問題なのか誰か教えていただければ幸いです。

4

1 に答える 1

1

closeEntry()その特定のエントリの日付を書いた後、忘れていたと思います。out.closeEntry()データを書き込む while ループの後に行う必要があります。こちらの例をご覧ください。

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

于 2020-05-12T21:32:46.057 に答える