Работа с ZIP/архивами в Kotlin: ZIP-InputStream и ZipFile

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

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

Начать курс

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

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

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

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

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

Все эти классы входят в стандартную библиотеку JDK, поэтому никаких дополнительных зависимостей не требуется.

Создание ZIP-архива

Для создания архива используется ZipOutputStream, который оборачивает FileOutputStream. Каждый файл добавляется через ZipEntry.

import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream

fun createZipArchive(sourceDir: String, zipFilePath: String) {
    val dir = File(sourceDir)
    val files = dir.listFiles() ?: return
    
    ZipOutputStream(FileOutputStream(zipFilePath)).use { zos ->
        for (file in files) {
            if (file.isFile) {
                // Создаём запись с именем файла
                val entry = ZipEntry(file.name)
                zos.putNextEntry(entry)
                
                // Копируем содержимое файла
                FileInputStream(file).use { fis ->
                    fis.copyTo(zos)
                }
                zos.closeEntry()
            }
        }
    }
    println("Архив создан: $zipFilePath")
}

// Пример вызова
fun main() {
    createZipArchive("/path/to/source", "/path/to/archive.zip")
}

Распаковка ZIP-архива

Распаковка выполняется через ZipInputStream. Считываем каждую запись и восстанавливаем файлы на диск.

import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.util.zip.ZipInputStream

fun extractZipArchive(zipFilePath: String, outputDir: String) {
    val outputFolder = File(outputDir).also { it.mkdirs() }
    
    ZipInputStream(FileInputStream(zipFilePath)).use { zis ->
        var entry = zis.nextEntry
        while (entry != null) {
            val fileName = entry.name
            val outputFile = File(outputFolder, fileName)
            
            // Создаём родительские директории, если нужно
            outputFile.parentFile?.mkdirs()
            
            // Распаковываем только файлы (не директории)
            if (!entry.isDirectory) {
                FileOutputStream(outputFile).use { fos ->
                    zis.copyTo(fos)
                }
            }
            entry = zis.nextEntry
        }
    }
    println("Архив распакован в: $outputDir")
}

// Пример вызова
fun main() {
    extractZipArchive("/path/to/archive.zip", "/path/to/extract")
}

Чтение содержимого архива без распаковки

Для просмотра файлов внутри ZIP без извлечения используйте ZipFile и итерацию по entries().

import java.io.File
import java.util.zip.ZipFile

fun listZipContents(zipFilePath: String) {
    ZipFile(File(zipFilePath)).use { zipFile ->
        println("Содержимое архива: ${zipFile.name}")
        println("Всего записей: ${zipFile.size()}")
        
        zipFile.entries().asSequence().forEach { entry ->
            val sizeKB = entry.size / 1024.0
            println("  ${if (entry.isDirectory) "[DIR]" else "[FILE]"} ${entry.name} (${"%.1f".format(sizeKB)} KB)")
        }
    }
}

// Пример вызова
fun main() {
    listZipContents("/path/to/archive.zip")
}

Добавление файлов в существующий архив

К сожалению, ZipOutputStream не поддерживает добавление записей в уже существующий архив без его пересоздания. Для этого необходимо сначала распаковать архив, добавить новые файлы и упаковать заново. Однако можно читать архив и записывать его копию с новыми данными.

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

fun addFileToArchive(zipFilePath: String, newFile: File) {
    val tempFile = File.createTempFile("temp_archive", ".zip")
    
    // Читаем старый архив и записываем в новый
    ZipInputStream(FileInputStream(zipFilePath)).use { zis ->
        ZipOutputStream(FileOutputStream(tempFile)).use { zos ->
            // К                    

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