Skip to content

Instantly share code, notes, and snippets.

@Madina-S
Last active December 7, 2020 17:46
Show Gist options
  • Save Madina-S/35850afb0adfac9e2bd3172c53571eb3 to your computer and use it in GitHub Desktop.
Save Madina-S/35850afb0adfac9e2bd3172c53571eb3 to your computer and use it in GitHub Desktop.
import okhttp3.internal.closeQuietly
import org.apache.commons.io.IOUtils
import uz.gid.updater.ZipUtil.zipBytes
import java.io.*
import java.nio.file.Files
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
object ZipUtil {
fun getDifference(old: ByteArray, new: ByteArray): ByteArray {
val oldZipFileSet: MutableSet<String> = LinkedHashSet()
val newZipFileSet: MutableSet<String> = LinkedHashSet()
val oldZipInputStreamSet = HashMap<String, InputStream>()
val newZipInputStreamSet = HashMap<String, InputStream>()
run {
val oldZipInputStream = ZipInputStream(ByteArrayInputStream(old))
val newZipInputStream = ZipInputStream(ByteArrayInputStream(new))
var entry: ZipEntry? = null
var fileName: String
var byteArrayInputStream: ByteArrayInputStream
while (oldZipInputStream.nextEntry?.let { entry = it } != null) {
if (entry!!.isDirectory.not()) {
fileName = entry!!.name
oldZipFileSet.add(fileName)
byteArrayInputStream = ByteArrayInputStream(IOUtils.toByteArray(oldZipInputStream.buffered()))
oldZipInputStreamSet[fileName] = byteArrayInputStream
}
}
while (newZipInputStream.nextEntry?.let { entry = it } != null) {
if (entry!!.isDirectory.not()) {
fileName = entry!!.name
newZipFileSet.add(fileName)
byteArrayInputStream = ByteArrayInputStream(IOUtils.toByteArray(newZipInputStream.buffered()))
newZipInputStreamSet[fileName] = byteArrayInputStream
}
}
oldZipInputStream.closeQuietly()
newZipInputStream.closeEntry()
}
val byteArrayOutputStream = ByteArrayOutputStream()
ZipOutputStream(byteArrayOutputStream).use { out ->
var zipEntry: Iterator<String> = oldZipFileSet.iterator()
var oldZipInputStream: InputStream
var newZipInputStream: InputStream
while (zipEntry.hasNext()) {
val name = zipEntry.next()
if (!newZipFileSet.contains(name)) {
println("$name not found in the new zip")
//file removed, there is no need to handle it
continue
}
try {
newZipFileSet.remove(name)
newZipInputStream = newZipInputStreamSet[name]!!
oldZipInputStream = oldZipInputStreamSet[name]!!
if (!streamsEqual(oldZipInputStream, newZipInputStream)) {
println("$name is changed")
newZipInputStream.reset()
write(out, name, newZipInputStream)
}
newZipInputStream.closeQuietly()
oldZipInputStream.closeQuietly()
} catch (e: Exception) {
println("$name: IO Error $e")
e.printStackTrace()
}
}
zipEntry = newZipFileSet.iterator()
while (zipEntry.hasNext()) {
val name = zipEntry.next()
println("$name not found in the old zip")
write(out, name, newZipInputStreamSet[name]!!)
}
val buffer = byteArrayOutputStream.toByteArray()
byteArrayOutputStream.closeQuietly()
return buffer
}
}
fun zipBytes(filename: String, input: ByteArray) {
val zos = ZipOutputStream(FileOutputStream(File(filename)))
val zis = ZipInputStream(ByteArrayInputStream(input))
var entry: ZipEntry? = null
while (zis.nextEntry?.let { entry = it } != null) {
zos.putNextEntry(entry!!)
IOUtils.copy(zis.buffered(), zos)
}
zos.close()
}
private fun write(out: ZipOutputStream, entryName: String, inputStream: InputStream) {
val zipEntry = ZipEntry(entryName)
out.putNextEntry(zipEntry)
IOUtils.copy(inputStream, out)
out.closeEntry()
}
@Throws(IOException::class)
private fun streamsEqual(stream1: InputStream, stream2: InputStream): Boolean {
val buf1 = ByteArray(4096)
val buf2 = ByteArray(4096)
var done1 = false
var done2 = false
return try {
while (!done1) {
var off1 = 0
var off2 = 0
while (off1 < buf1.size) {
val count = stream1.read(buf1, off1, buf1.size - off1)
if (count < 0) {
done1 = true
break
}
off1 += count
}
while (off2 < buf2.size) {
val count = stream2.read(buf2, off2, buf2.size - off2)
if (count < 0) {
done2 = true
break
}
off2 += count
}
if (off1 != off2 || done1 != done2) return false
for (i in 0 until off1) {
if (buf1[i] != buf2[i]) return false
}
}
true
} finally {
stream1.close()
stream2.close()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment