如何使用 zip4j 和 outputstream 压缩文件夹和子文件夹
How to zip folder and sub-folder using zip4j and outputstream
在我正在编写的程序中,我获取了用户保存 zip 文件的位置的 uri。然后,我尝试使用 zip4j 库和 Android 中的 outpustream 压缩文件和文件夹。我修改了 this Whosebug answer 中的代码并改用 zip4j。我修改后的代码生成了 zip 文件,但它已损坏。
这是我用 Kotlin 编写的代码:
class ZipBuilder {
private fun buildZipParameters(compressionMethod: CompressionMethod, compressionLevel: CompressionLevel,
encrypt: Boolean,
encryptionMethod: EncryptionMethod?,
aesKeyStrength: AesKeyStrength?
): ZipParameters? {
val zipParameters = ZipParameters()
zipParameters.compressionMethod = compressionMethod
zipParameters.compressionLevel = compressionLevel
return zipParameters
}
fun zipFileAtPath(sourcePath: String?, toLocation: ParcelFileDescriptor?): Boolean {
println("zipFileAtPath is called")
val BUFFER = 2048
val sourceFile = File(sourcePath!!)
val zipParameters = buildZipParameters(CompressionMethod.DEFLATE, CompressionLevel.NORMAL,
false, null, null)
try {
var origin: BufferedInputStream? = null
val desc = toLocation
val dest = FileOutputStream(desc!!.fileDescriptor)
val out = ZipOutputStream(BufferedOutputStream(dest))
if (sourceFile.isDirectory) {
zipParameters.rootFolderNameInZip = sourcePath
zipSubFolder(out, sourceFile, sourceFile.parent!!.length, zipParameters!!)
} else {
val data = ByteArray(BUFFER)
val fi = FileInputStream(sourcePath)
origin = BufferedInputStream(fi, BUFFER)
zipParameters!!.fileNameInZip = getLastPathComponent(sourcePath)
zipParameters.lastModifiedFileTime = sourceFile.lastModified()
out.putNextEntry(zipParameters)
var count: Int = 0
while (fi.read(data).also({ count = it }) != -1) {
out.write(data, 0, count)
}
}
out.close()
} catch (e: java.lang.Exception) {
e.printStackTrace()
return false
}
return true
}
@Throws(IOException::class)
private fun zipSubFolder(
out: ZipOutputStream, folder: File, basePathLength: Int, zipParameters: ZipParameters
) {
val BUFFER = 2048
val fileList = folder.listFiles()
var origin: BufferedInputStream
fileList?.forEach { file ->
if (file.isDirectory) {
zipSubFolder(out, file, basePathLength, zipParameters)
} else {
val data = ByteArray(BUFFER)
val unmodifiedFilePath = file.path
val relativePath = unmodifiedFilePath
.substring(basePathLength)
val fi = FileInputStream(unmodifiedFilePath)
origin = BufferedInputStream(fi, BUFFER)
zipParameters.fileNameInZip = relativePath
zipParameters.lastModifiedFileTime = file.lastModified()
out.putNextEntry(zipParameters)
var count: Int = 0
while (fi.read(data).also({ count = it }) != -1) {
out.write(data, 0, count)
}
origin.close()
}
}
}
fun getLastPathComponent(filePath: String): String? {
val segments = filePath.split("/").toTypedArray()
return if (segments.size == 0) "" else segments[segments.size - 1]
}
}
如果有人能告诉我可能是什么问题,我将不胜感激。
我猜你忘记了 closeEntry()
在为该特定条目写下日期之后。你需要在写入数据的while循环之后做out.closeEntry()
。看看例子 here.
while (fi.read(data).also({ count = it }) != -1) {
out.write(data, 0, count)
}
out.closeEntry() // --> close entry after writing data
在我正在编写的程序中,我获取了用户保存 zip 文件的位置的 uri。然后,我尝试使用 zip4j 库和 Android 中的 outpustream 压缩文件和文件夹。我修改了 this Whosebug answer 中的代码并改用 zip4j。我修改后的代码生成了 zip 文件,但它已损坏。
这是我用 Kotlin 编写的代码:
class ZipBuilder {
private fun buildZipParameters(compressionMethod: CompressionMethod, compressionLevel: CompressionLevel,
encrypt: Boolean,
encryptionMethod: EncryptionMethod?,
aesKeyStrength: AesKeyStrength?
): ZipParameters? {
val zipParameters = ZipParameters()
zipParameters.compressionMethod = compressionMethod
zipParameters.compressionLevel = compressionLevel
return zipParameters
}
fun zipFileAtPath(sourcePath: String?, toLocation: ParcelFileDescriptor?): Boolean {
println("zipFileAtPath is called")
val BUFFER = 2048
val sourceFile = File(sourcePath!!)
val zipParameters = buildZipParameters(CompressionMethod.DEFLATE, CompressionLevel.NORMAL,
false, null, null)
try {
var origin: BufferedInputStream? = null
val desc = toLocation
val dest = FileOutputStream(desc!!.fileDescriptor)
val out = ZipOutputStream(BufferedOutputStream(dest))
if (sourceFile.isDirectory) {
zipParameters.rootFolderNameInZip = sourcePath
zipSubFolder(out, sourceFile, sourceFile.parent!!.length, zipParameters!!)
} else {
val data = ByteArray(BUFFER)
val fi = FileInputStream(sourcePath)
origin = BufferedInputStream(fi, BUFFER)
zipParameters!!.fileNameInZip = getLastPathComponent(sourcePath)
zipParameters.lastModifiedFileTime = sourceFile.lastModified()
out.putNextEntry(zipParameters)
var count: Int = 0
while (fi.read(data).also({ count = it }) != -1) {
out.write(data, 0, count)
}
}
out.close()
} catch (e: java.lang.Exception) {
e.printStackTrace()
return false
}
return true
}
@Throws(IOException::class)
private fun zipSubFolder(
out: ZipOutputStream, folder: File, basePathLength: Int, zipParameters: ZipParameters
) {
val BUFFER = 2048
val fileList = folder.listFiles()
var origin: BufferedInputStream
fileList?.forEach { file ->
if (file.isDirectory) {
zipSubFolder(out, file, basePathLength, zipParameters)
} else {
val data = ByteArray(BUFFER)
val unmodifiedFilePath = file.path
val relativePath = unmodifiedFilePath
.substring(basePathLength)
val fi = FileInputStream(unmodifiedFilePath)
origin = BufferedInputStream(fi, BUFFER)
zipParameters.fileNameInZip = relativePath
zipParameters.lastModifiedFileTime = file.lastModified()
out.putNextEntry(zipParameters)
var count: Int = 0
while (fi.read(data).also({ count = it }) != -1) {
out.write(data, 0, count)
}
origin.close()
}
}
}
fun getLastPathComponent(filePath: String): String? {
val segments = filePath.split("/").toTypedArray()
return if (segments.size == 0) "" else segments[segments.size - 1]
}
}
如果有人能告诉我可能是什么问题,我将不胜感激。
我猜你忘记了 closeEntry()
在为该特定条目写下日期之后。你需要在写入数据的while循环之后做out.closeEntry()
。看看例子 here.
while (fi.read(data).also({ count = it }) != -1) {
out.write(data, 0, count)
}
out.closeEntry() // --> close entry after writing data