使用方法:通過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
}
複製程式碼