Работа с ZIP/архивами в Kotlin: полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Работа с ZIP/архивами в Kotlin: полное руководство

В современной разработке на Kotlin (особенно для JVM и Android) часто возникает необходимость работать с ZIP-архивами: упаковывать логи, распаковывать ресурсы, создавать резервные копии или передавать данные в сжатом виде. В этой статье мы подробно разберем, как работать с ZIP-архивами в Kotlin, используя встроенные возможности Java (пакет java.util.zip), а также рассмотрим удобные расширения и альтернативы.

Зачем нужна работа с архивами в Kotlin?

  • Экономия места — сжатие данных при хранении на диске.
  • Удобство передачи — один архив вместо множества файлов.
  • Безопасность — возможность шифрования (с дополнительными библиотеками).
  • Работа с ресурсами — распаковка конфигураций или обновлений.

Основные классы Java для работы с ZIP

Kotlin полностью совместим с Java, поэтому для работы с архивами мы используем следующие классы из java.util.zip:

  • ZipOutputStream — для создания архива.
  • ZipInputStream — для чтения архива.
  • ZipEntry — представляет отдельный файл/папку внутри архива.
  • ZipFile — удобный класс для чтения существующего архива.

Пример 1: Создание ZIP-архива в Kotlin

Создадим архив, который содержит несколько файлов и папок. Используем ZipOutputStream и BufferedOutputStream для повышения производительности.

import java.io.*
import java.util.zip.*

fun createZipArchive(
    filesToZip: List<File>,
    outputZipPath: String
) {
    ZipOutputStream(BufferedOutputStream(FileOutputStream(outputZipPath))).use { zos ->
        for (file in filesToZip) {
            if (file.isDirectory) {
                // Добавляем пустую папку
                zos.putNextEntry(ZipEntry("${file.name}/"))
                zos.closeEntry()
                continue
            }
            // Добавляем файл
            val entry = ZipEntry(file.name)
            zos.putNextEntry(entry)
            FileInputStream(file).use { fis ->
                fis.copyTo(zos)
            }
            zos.closeEntry()
        }
    }
    println("Архив создан: $outputZipPath")
}

fun main() {
    val files = listOf(
        File("document.txt"),
        File("image.png"),
        File("configs") // папка
    )
    createZipArchive(files, "output.zip")
}

Пример 2: Чтение содержимого ZIP-архива

Для просмотра списка файлов внутри архива удобно использовать ZipFile.

import java.util.zip.ZipFile

fun listZipContents(zipPath: String) {
    ZipFile(zipPath).use { zip ->
        println("Содержимое архива $zipPath:")
        zip.entries().asSequence().forEach { entry ->
            val size = if (entry.isDirectory) "папка" else "${entry.size} байт"
            println("- ${entry.name} ($size)")
        }
    }
}

fun main() {
    listZipContents("output.zip")
}

Пример 3: Распаковка ZIP-архива

Извлечем все файлы из архива в указанную папку. Обратите внимание на обработку вложенных папок.

import java.io.*
import java.util.zip.ZipInputStream

fun extractZip(
    zipPath: String,
    outputDir: String = "extracted"
) {
    val destDir = File(outputDir)
    destDir.mkdirs()

    ZipInputStream(BufferedInputStream(FileInputStream(zipPath))).use { zis ->
        var entry = zis.nextEntry
        while (entry != null) {
            val file = File(destDir, entry.name)
            if (entry.isDirectory) {
                file.mkdirs()
            } else {
                // Создаем родительские папки
                file.parentFile?.mkdirs()
                BufferedOutputStream(FileOutputStream(file)).use { bos ->
                    zis.copyTo(bos)
                }
            }
            zis.closeEntry()
            entry = zis.nextEntry
        }
    }
    println("Архив распакован в $outputDir")
}

fun main() {
    extractZip("output.zip", "my_output")
}

Расширения Kotlin для удобной работы с ZIP

Kotlin позволяет писать элегантные функции-расширения. Вот несколько полезных:

// Расширение для File
fun File.zipTo(destination: String) {
    val files = if (this.isDirectory) this.walkTopDown().toList() else listOf(this)
    ZipOutputStream(BufferedOutputStream(FileOutputStream(destination))).use { zos ->
        for (file in files) {
            val entryName = if (this.isDirectory) {
                file.relativeTo(this                    

Рекомендаций