使用方法:通过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<File>, 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
}
复制代码