Por que trabalhar com arquivos em Kotlin não é doloroso
\n\nImagine: você está escrevendo um aplicativo que precisa salvar as configurações do usuário, registrar erros ou processar arquivos CSV com milhares de linhas. Em Java, dezenas de classes BufferedReader, FileWriter e infinitos try-catch são responsáveis por isso. E em Kotlin? A linguagem criada pela JetBrains não apenas "simplifica" o Java — ela repensa o trabalho com dados. Aqui, os arquivos são abertos com uma única linha, e os erros são tratados de forma elegante.
Neste artigo, vamos abordar o trabalho com arquivos e sistema de arquivos em Kotlin, desde operações básicas até técnicas avançadas. Você aprenderá como ler e escrever arquivos, gerenciar diretórios, trabalhar com JSON e CSV, além de evitar erros comuns. Pronto? Vamos nessa!
\n\nFundamentos: como o Kotlin simplifica o Java IO
\n\nA principal vantagem do Kotlin são as extension-functions. Em vez de escrever dezenas de linhas para ler um arquivo, você usa uma única função .readText() ou .readLines(). Vamos ver exemplos concretos.
Leitura completa do arquivo
\nA maneira mais simples de ler um arquivo de texto é usar readText(). Este método retorna uma string com o conteúdo do arquivo. Importante: o arquivo será fechado automaticamente após a leitura.
import java.io.File\n\nfun main() {\n val content = File("example.txt").readText()\n println(content)\n}\n\nSe o arquivo for grande, é melhor ler linha por linha:
\n\nval lines = File("example.txt").readLines()\nlines.forEach { line -> println(line) }\n\nE se precisar ler como fluxo (por exemplo, para processar logs grandes):
\n\nFile("example.txt").useLines { lines ->\n lines.forEach { line ->\n // Processamento de cada linha\n println(line)\n }\n}\n\nObserve o useLines() — é uma função que garante o fechamento do recurso após a conclusão do bloco. Parece mágico, mas funciona como try-with-resources em Java, só que mais curto.
Escrita em arquivo
\nA escrita de dados em Kotlin também é intuitiva. Aqui estão três opções:
\n\n// 1. Sobrescrever o arquivo\nFile("output.txt").writeText("Olá, mundo!")\n\n// 2. Adicionar ao final do arquivo\nFile("output.txt").appendText("Nova linha\\n")\n\n// 3. Escrever uma lista de strings\nval list = listOf("linha1", "linha2", "linha3")\nFile("output.txt").writeText(list.joinToString("\\n"))\n\nA propósito, se você estiver trabalhando com dados binários (imagens, arquivos compactados), use writeBytes() e readBytes():
val imageBytes = File("image.png").readBytes()\n// Processamento dos bytes...\nFile("copy.png").writeBytes(imageBytes)\n\nGerenciamento do sistema de arquivos: criação, exclusão, movimentação
\n\nKotlin não reinventa a roda, mas torna o trabalho com o sistema de arquivos mais conveniente. Todas as operações estão disponíveis através da classe java.io.File com extensões.
Criação de diretórios
\nPara criar um diretório (e todos os diretórios pai, se não existirem):
\n\nval dir = File("data/logs/2024")\nval created = dir.mkdirs() // Retorna true se criado\nprintln("Diretório criado: $created")\n\nObserve: mkdir() cria apenas a última pasta, enquanto mkdirs() cria toda a cadeia.
Verificação de existência e exclusão
\n\nval file = File("temp.txt")\nif (file.exists()) {\n if (file.delete()) {\n println("Arquivo excluído")\n } else {\n println("Não foi possível excluir")\n }\n}\n\n// Exclusão recursiva de diretório\nFile("data").deleteRecursively()\n\nCuidado com deleteRecursively() — é uma operação irreversível. Verifique duas vezes se está excluindo os dados corretos.
Movimentação e cópia
\n\nval source = File("old.txt")\nval target = File("new_dir/new.txt")\n\n// Movimentação (mov