kotlin对ZipInputStream与ZipOutputStream的一些拓展工具(压缩,解压)

使用方法:通过file或流直接创建ZipInputStream ZipOutputStream

val zipOut = File("C:\\Users\\admin\\Desktop\\output.zip").zipOutputStream()
val zipIn = File("C:\\Users\\admin\\Desktop\\output.zip").zipInputStream()
val zipOut = xxOutputStream.zipOutputStream()
val zipIn = xxInputStream.zipInputStream()
复制代码

对多文件,文件夹进行压缩处理(支持空文件夹)

File("C:\\Users\\admin\\Desktop\\output.zip")
            .zipOutputStream()
            .zipFrom(
                    "C:\\Users\\admin\\Desktop\\SophixPatchTool_windows",
                    "F:\\MUSIC\\Justin Bieber - Love Yourself.flac")
//上述代码将SophixPatchTool_windows文件夹与Justin Bieber - Love Yourself.flac压缩到C:\\Users\\admin\\Desktop\\output.zip目录下

复制代码

将zip文件压缩到指定目录

将zip文件压缩到指定目录C:\\Users\\admin\\Desktop\\66
File("C:\\Users\\admin\\Desktop\\output.zip").unZipTo("C:\\Users\\admin\\Desktop\\66")
或者
File("C:\\Users\\admin\\Desktop\\output.zip") unZipTo "C:\\Users\\admin\\Desktop\\66"
复制代码

代码主要是一些递归的算法,以及大量使用了kotlin的拓展函数,并且使用了中缀表达式 并没有比较难的地方,代码贴上


fun File.zipInputStream() = ZipInputStream(this.inputStream())

fun File.zipOutputStream() = ZipOutputStream(this.outputStream())

fun InputStream.zipInputStream() = ZipInputStream(this)

fun OutputStream.zipOutputStream() = ZipOutputStream(this)

infix fun File.unZipTo(path: String) {
    //使用GBK编码,避免压缩中文文件名乱码
    checkUnzipFolder(path)
    ZipFile(this, Charset.forName("GBK")) unZipTo path
}

infix fun ZipFile.unZipTo(path: String) {
    checkUnzipFolder(path)
    for (entry in entries()) {
        //判断是否为文件夹
        if (entry.isDirectory) {
            File("${path}/${entry.name}").mkdirs()
        } else {
            val input = getInputStream(entry)
            val outputFile = File("${path}/${entry.name}")
            if (!outputFile.exists()) outputFile.smartCreateNewFile()
            val output = outputFile.outputStream()
            input.writeTo(output, DEFAULT_BUFFER_SIZE)
        }
    }
}

/**
 * 检查路径正确性
 */
private fun checkUnzipFolder(path: String) {
    val file = File(path)
    if (file.isFile) throw RuntimeException("路径不能是文件")
    if (!file.exists()) {
        if (!file.mkdirs()) throw RuntimeException("创建文件夹失败")
    }
}

fun ZipOutputStream.zipFrom(vararg srcs: String) {

    val files = srcs.map { File(it) }

    files.forEach {
        if (it.isFile) {
            zip(arrayOf(it), null)
        } else if (it.isDirectory) {
            zip(it.listFiles(), it.name)
        }
    }
    this.close()
}

private fun ZipOutputStream.zip(files: Array, path: String?) {
    //前缀,用于构造路径
    val prefix = if (path == null) "" else "$path/"

    if (files.isEmpty()) createEmptyFolder(prefix)

    files.forEach {
        if (it.isFile) {
            val entry = ZipEntry("$prefix${it.name}")
            val ins = it.inputStream().buffered()
            putNextEntry(entry)
            ins.writeTo(this, DEFAULT_BUFFER_SIZE, closeOutput = false)
            closeEntry()
        } else {
            zip(it.listFiles(), "$prefix${it.name}")
        }
    }
}

/**
 * inputstream内容写入outputstream
 */
fun InputStream.writeTo(outputStream: OutputStream, bufferSize: Int = 1024 * 2,
                        closeInput: Boolean = true, closeOutput: Boolean = true) {

    val buffer = ByteArray(bufferSize)
    val br = this.buffered()
    val bw = outputStream.buffered()
    var length = 0

    while ({ length = br.read(buffer);length != -1 }()) {
        bw.write(buffer, 0, length)
    }

    bw.flush()

    if (closeInput) {
        close()
    }

    if (closeOutput) {
        outputStream.close()
    }
}

/**
 * 生成一个压缩文件的文件夹
 */
private fun ZipOutputStream.createEmptyFolder(location: String) {
    putNextEntry(ZipEntry(location))
    closeEntry()
}

fun File.smartCreateNewFile(): Boolean {

    if (exists()) return true
    if (parentFile.exists()) return createNewFile()

    if (parentFile.mkdirs()) {
        if (this.createNewFile()) {
            return true
        }
    }
    return false
}

复制代码

你可能感兴趣的:(移动开发)