Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何压缩文件夹&;使用ZipoutStream在Kotlin中包含文件的子文件夹?_Android_Kotlin - Fatal编程技术网

Android 如何压缩文件夹&;使用ZipoutStream在Kotlin中包含文件的子文件夹?

Android 如何压缩文件夹&;使用ZipoutStream在Kotlin中包含文件的子文件夹?,android,kotlin,Android,Kotlin,我的文件列表安排在不同的目录,一些目录将有子目录和文件在其中。我无法成功地将相同的目录结构放入zip文件中。这是我的密码: fun zipAll(directory: String, zipFile: String) { val sourceFile = File(directory) ZipOutputStream(BufferedOutputStream(FileOutputStream(zipFile))).use { zipFiles(it, sourceFile)

我的文件列表安排在不同的目录,一些目录将有子目录和文件在其中。我无法成功地将相同的目录结构放入zip文件中。这是我的密码:

fun zipAll(directory: String, zipFile: String) {
val sourceFile = File(directory)

 ZipOutputStream(BufferedOutputStream(FileOutputStream(zipFile))).use {
       zipFiles(it, sourceFile)
   }
}

private fun zipFiles(zipOut: ZipOutputStream, directory: File) {

val data = ByteArray(1024)

zipOut.use {

    if (directory.isDirectory) {
        //Adding directory
        it.putNextEntry(ZipEntry(directory.name))
    } else {
        zipFiles(zipOut, directory)
    }

    for (f in directory.listFiles()) {

        if (!f.name.contains(".zip") && f.exists()) {

            //Adding file

            FileInputStream(f).use { fi ->
                BufferedInputStream(fi).use { origin ->
                    val entry = ZipEntry(f.name)
                    it.putNextEntry(entry)
                    while (true) {
                        val readBytes = origin.read(data)
                        if (readBytes == -1) {
                            break
                        }
                        it.write(data, 0, readBytes)
                    }
                }
            }
        }
    }
}
}

我解决了,这里是完整的解决方案:

fun zipAll(directory: String, zipFile: String) {
    val sourceFile = File(directory)

    ZipOutputStream(BufferedOutputStream(FileOutputStream(zipFile))).use {
        it.use {
            zipFiles(it, sourceFile, "")
        }
    }
}

private fun zipFiles(zipOut: ZipOutputStream, sourceFile: File, parentDirPath: String) {

    val data = ByteArray(2048)

    for (f in sourceFile.listFiles()) {

        if (f.isDirectory) {
            val entry = ZipEntry(f.name + File.separator)
            entry.time = f.lastModified()
            entry.isDirectory
            entry.size = f.length()

            Log.i("zip", "Adding Directory: " + f.name)
            zipOut.putNextEntry(entry)

            //Call recursively to add files within this directory
            zipFiles(zipOut, f, f.name)
        } else {

            if (!f.name.contains(".zip")) { //If folder contains a file with extension ".zip", skip it
                FileInputStream(f).use { fi ->
                    BufferedInputStream(fi).use { origin ->
                        val path = parentDirPath + File.separator + f.name
                        Log.i("zip", "Adding file: $path")
                        val entry = ZipEntry(path)
                        entry.time = f.lastModified()
                        entry.isDirectory
                        entry.size = f.length()
                        zipOut.putNextEntry(entry)
                        while (true) {
                            val readBytes = origin.read(data)
                            if (readBytes == -1) {
                                break
                            }
                            zipOut.write(data, 0, readBytes)
                        }
                    }
                }
            } else {
                zipOut.closeEntry()
                zipOut.close()
            }
        }
    }
}
用法:

zipAll("Path of source files to Zip", "Path for Zip to Export")

这会将嵌套文件夹压缩到平面目录结构中。如果要保留嵌套结构,请在isDirectory If case中使用以下代码:

if (f.isDirectory) {
  val path = if (parentDirPath == "") {
    f.name
  } else {
    parentDirPath + File.separator + f.name
  }
  val entry = ZipEntry(path + File.separator)
  entry.time = f.lastModified()
  entry.isDirectory
  entry.size = f.length()
  zipOut.putNextEntry(entry)
  //Call recursively to add files within this directory
  zipFiles(zipOut, f, path)
} else {

这是我的完整解决方案。它不忽略zip,也尊重文件夹层次结构,如


这是一个有点老的问题,但我想我有一个更好的解决方案,给你:

    val inputDirectory = File("/home/fred")
    val outputZipFile = File.createTempFile("out", ".zip")
    ZipOutputStream(BufferedOutputStream(FileOutputStream(outputZipFile))).use { zos ->
        inputDirectory.walkTopDown().forEach { file ->
            val zipFileName = file.absolutePath.removePrefix(inputDirectory.absolutePath).removePrefix("/")
            val entry = ZipEntry( "$zipFileName${(if (file.isDirectory) "/" else "" )}")
            zos.putNextEntry(entry)
            if (file.isFile) {
                file.inputStream().copyTo(zos)
            }
        }
    }

您可以通过测试'file'变量过滤掉forEach循环中的一些文件(例如过滤掉zip文件以防止压缩)

此脚本中可能存在问题,一些文件未压缩,脚本卡住。Umair Adil版本也会出现这种情况。
    val inputDirectory = File("/home/fred")
    val outputZipFile = File.createTempFile("out", ".zip")
    ZipOutputStream(BufferedOutputStream(FileOutputStream(outputZipFile))).use { zos ->
        inputDirectory.walkTopDown().forEach { file ->
            val zipFileName = file.absolutePath.removePrefix(inputDirectory.absolutePath).removePrefix("/")
            val entry = ZipEntry( "$zipFileName${(if (file.isDirectory) "/" else "" )}")
            zos.putNextEntry(entry)
            if (file.isFile) {
                file.inputStream().copyTo(zos)
            }
        }
    }