Create file ZIP in Kotlin

后端 未结 4 1147
别跟我提以往
别跟我提以往 2020-12-31 05:28

I\'m trying to create a zip file in Kotlin. this is the code:

fun main(args: Array) {
var files: Array = arrayOf(\"/home/matte/th         


        
相关标签:
4条回答
  • 2020-12-31 06:06

    Here is a solution working with subfolders:

    fun addFolderToZip(
        folder: String,
        destination: String,
        zipFileName: String = folder.substring(folder.lastIndexOf("/"))
    ) {
    
        val folderToZip = File(folder)
        var out: ZipOutputStream? = null
        try {
            out = ZipOutputStream(
                BufferedOutputStream(FileOutputStream("$destination/$zipFileName"))
            )
            recursivelyAddZipEntries(folderToZip, folderToZip.absolutePath, out)
        } catch (e: Exception) {
            Log.e("ZIP Err", e.message)
        } finally {
            out?.close()
        }
    
    }
    
    
    private fun recursivelyAddZipEntries(
        folder: File,
        basePath: String,
        out: ZipOutputStream
    ) {
    
        val files = folder.listFiles() ?: return
        for (file in files) {
    
            if (file.isDirectory) {
                recursivelyAddZipEntries(file, basePath, out)
            } else {
                val origin = BufferedInputStream(FileInputStream(file))
                origin.use {
                    val entryName = file.path.substring(basePath.length)
                    out.putNextEntry(ZipEntry(entryName))
                    origin.copyTo(out, 1024)
                }
            }
    
        }
    
    }
    
    0 讨论(0)
  • 2020-12-31 06:18

    1) You are writing an empty byte array to the out for each line of an input file.

    2) There is no need in BufferedReader because it is enough to read and write bytes instead of lines (which would lead the unpacked content not to be matched with the original).

    3) All streams should be closed in the case of exceptions. Use method use like try-with-resources in java.

    4) val instead var there possible

    5) Don't use absolute paths except for the quick test snippets.

    6) This snippet is not in idiomatic way for Kotlin (see the Todd's answer)

    So this is how it should work (though in the Java way):

    fun main(args: Array<String>) {
        val files: Array<String> = arrayOf("/home/matte/theres_no_place.png", "/home/matte/vladstudio_the_moon_and_the_ocean_1920x1440_signed.jpg")
        ZipOutputStream(BufferedOutputStream(FileOutputStream("/home/matte/Desktop/test.zip"))).use { out ->
            val data = ByteArray(1024)
            for (file in files) {
                FileInputStream(file).use { fi ->
                    BufferedInputStream(fi).use { origin ->
                        val entry = ZipEntry(file)
                        out.putNextEntry(entry)
                        while (true) {
                            val readBytes = origin.read(data)
                            if (readBytes == -1) {
                                break
                            }
                            out.write(data, 0, readBytes)
                        }
                    }
                }
            }
        }
    }
    

    EDIT: I've ran this snippet with my files and it worked OK.

    0 讨论(0)
  • 2020-12-31 06:19

    I did a mix:

    fun main(args: Array<String>) {
        val files: Array<String> = arrayOf("/home/matte/theres_no_place.png", "/home/matte/vladstudio_the_moon_and_the_ocean_1920x1440_signed.jpg")
        ZipOutputStream(BufferedOutputStream(FileOutputStream("/home/matte/Desktop/test.zip"))).use { out ->
            for (file in files) {
                FileInputStream(file).use { fi ->
                    BufferedInputStream(fi).use { origin ->
                        val entry = ZipEntry(file.substring(file.lastIndexOf("/")))
                        out.putNextEntry(entry)
                        origin.copyTo(out, 1024)
                    }
                }
            }
        }
    }
    

    It works perfectly!

    0 讨论(0)
  • 2020-12-31 06:27

    If you use Kotlin's IOStreams.copyTo() extension, it will do the copying work for you, and that ended up working for me.

    So replace this:

    origin.buffered(1024).reader().forEachLine {
        out.write(data)
    }
    

    With this:

    origin.copyTo(out, 1024)
    

    I also had issues with the ZipEntry having a leading slash, but that could just be because I'm on Windows.

    Note: I didn't end up needing to call closeEntry() to get this to work but it is recommended.

    0 讨论(0)
提交回复
热议问题