I use ZipOutputStream to compress the content of a folder into a Zip file. Below is my working code. But it creates corrupt DOCX files. Trying to extract them on macOS fails.
private const val DEFAULT_BUFFER_SIZE = 1024 * 4
fun zip(source: String?, destination: String?, contentsOnly: Boolean, compression: Int) {
try {
val zipOut = ZipOutputStream(FileOutputStream(destination))
val srcFile = File(source)
// Compression Level
val compressionLevel: Int = when(compression) {
0 -> Deflater.DEFAULT_COMPRESSION
1 -> Deflater.NO_COMPRESSION
2 -> Deflater.BEST_SPEED
3 -> Deflater.BEST_COMPRESSION
else -> {
Deflater.DEFAULT_COMPRESSION
}
}
zipOut.setLevel(compressionLevel)
zipOut.setMethod(ZipOutputStream.DEFLATED)
if (contentsOnly && srcFile.isDirectory) {
for (fileName in srcFile.list()) {
addToZip("", source + File.separator + fileName, zipOut)
}
} else {
if (source != null) {
addToZip("", source, zipOut)
}
}
zipOut.flush()
zipOut.finish()
zipOut.close()
println("Successfully created $destination")
} catch (error: Exception) {
println("Failed")
}
}
private fun addToZip(path: String, srcFile: String, zipOut: ZipOutputStream) {
val file = File(srcFile)
val filePath = if ("" == path) file.name else path + File.separator + file.name
if (file.isDirectory) {
for (fileName in file.list()) {
addToZip(filePath, srcFile + File.separator + fileName, zipOut)
}
} else {
zipOut.putNextEntry(ZipEntry(filePath))
val `in` = FileInputStream(srcFile)
val buffer = ByteArray(DEFAULT_BUFFER_SIZE)
var len: Int
while (`in`.read(buffer).also { len = it } != -1) {
zipOut.write(buffer, 0, len)
}
}
}
I use the code e.g. to compress the folder "paragraph", which you can find here: https://github.com/stiv-yakovenko/toptal-docx/tree/master/paragraph. The Zip file is generated, I can view the Structure inside Android Studio, but if I try to extract it, I get the message the file is corrupt. Compress other folders, which are not based on OfficeOpenXml (.docx, .xsxl etc.) works fine.