Trabalho com ZIP/arquivos em Kotlin
No desenvolvimento moderno com Kotlin (tanto para JVM quanto para Android), surge frequentemente a necessidade de compactar arquivos em arquivos ZIP ou extrair dados deles. A biblioteca padrão do Java (java.util.zip) fornece todas as classes necessárias que funcionam perfeitamente também em Kotlin. Neste artigo, abordaremos detalhadamente três operações principais: criação de arquivo, leitura de conteúdo e descompactação de arquivos.
1. Criação de arquivo ZIP (compactação de arquivos)
Para criar um arquivo, utiliza-se ZipOutputStream. Cada arquivo é adicionado como uma entrada separada (ZipEntry). Vejamos um exemplo que compacta vários arquivos em um único arquivo.
import java.io.Fileimport java.io.FileInputStreamimport java.io.FileOutputStreamimport java.util.zip.ZipEntryimport java.util.zip.ZipOutputStream
fun createZip( filesToZip: List<File>, outputZipFile: File) { ZipOutputStream(FileOutputStream(outputZipFile)).use { zipOut -> for (file in filesToZip) { // Cria uma entrada com o nome do arquivo val entry = ZipEntry(file.name) zipOut.putNextEntry(entry)
// Lê o arquivo original e escreve no arquivo FileInputStream(file).use { fis -> fis.copyTo(zipOut) } zipOut.closeEntry() } }}
fun main() { val files = listOf( File("document.txt"), File("image.png"), File("data.json") ) val archive = File("my_archive.zip") createZip(files, archive) println("Arquivo criado: ${archive.absolutePath}")}Observe o uso de .use { ... } — é um fechamento seguro de recursos, equivalente ao try-with-resources em Java. Se for necessário compactar arquivos de subdiretórios, será preciso percorrer recursivamente os diretórios e salvar os caminhos relativos no nome do ZipEntry.
2. Leitura do conteúdo do arquivo (visualização da lista de arquivos)
Às vezes, é necessário apenas visualizar quais arquivos estão dentro do arquivo, sem extraí-los. Para isso, utiliza-se ZipFile ou ZipInputStream. A primeira opção é mais conveniente se o arquivo já existir e não for muito grande.
import java.io.Fileimport java.util.zip.ZipFile
fun listZipContent(zipFile: File) { ZipFile(zipFile).use { zip -> val entries = zip.entries() while (entries.hasMoreElements()) { val entry = entries.nextElement() println("${entry.name} (${entry.size} bytes)") } }}
fun main() { val archive = File("my_archive.zip") if (archive.exists()) { listZipContent(archive) } else { println("Arquivo não encontrado") }}O método entries() retorna uma enumeração de todas as entradas. Para cada entrada, estão disponíveis o nome, tamanho, data de modificação e flags (por exemplo, se a entrada é um diretório).
3. Descompactação de arquivo ZIP (extração de arquivos)
Para extrair arquivos, é conveniente usar ZipInputStream. Ele lê o arquivo sequencialmente, entrada por entrada. Abaixo está um exemplo de descompactação completa em uma pasta especificada.
import java.io.Fileimport java.io.FileInputStreamimport java.io.FileOutputStreamimport java.util.zip.ZipInputStream
fun extractZip( zipFile: File, outputDir: File) { if (!outputDir.exists()) { outputDir.mkdirs() }
ZipInputStream(FileInputStream(zipFile)).use { zis -> var entry = zis.nextEntry while (entry != null) { val targetFile = File(outputDir, entry.name)
// Cria diretórios pai, se necessário targetFile.parentFile?.mkdirs()
// Se a entrada for um diretório, apenas cria-o if (entry.isDirectory) { targetFile.mkdirs() } else {