Por qué trabajar con archivos en Kotlin no es doloroso
\n\nImagina: estás escribiendo una aplicación que debe guardar la configuración del usuario, registrar errores o procesar archivos CSV con miles de líneas. En Java, esto implica decenas de clases BufferedReader, FileWriter e infinitos try-catch. ¿Y en Kotlin? El lenguaje creado por JetBrains no solo "simplifica" Java, sino que replantea el trabajo con datos. Aquí los archivos se abren con una sola línea y los errores se manejan de forma elegante.
En este artículo, analizaremos el trabajo con archivos y el sistema de archivos en Kotlin, desde operaciones básicas hasta técnicas avanzadas. Aprenderás a leer y escribir archivos, gestionar directorios, trabajar con JSON y CSV, y evitar errores típicos. ¿Listo? ¡Vamos allá!
\n\nFundamentos: cómo Kotlin simplifica Java IO
\n\nLa característica principal de Kotlin son las funciones de extensión. En lugar de escribir decenas de líneas para leer un archivo, usas una sola función .readText() o .readLines(). Veamos ejemplos concretos.
Lectura completa de un archivo
\nLa forma más sencilla de leer un archivo de texto es usar readText(). Este método devuelve una cadena con el contenido del archivo. Importante: el archivo se cerrará automáticamente después de la lectura.
import java.io.File\n\nfun main() {\n val content = File("example.txt").readText()\n println(content)\n}\n\nSi el archivo es grande, es mejor leerlo línea por línea:
\n\nval lines = File("example.txt").readLines()\nlines.forEach { line -> println(line) }\n\nY si necesitas leerlo como flujo (por ejemplo, para procesar registros grandes):
\n\nFile("example.txt").useLines { lines ->\n lines.forEach { line ->\n // Procesamiento de cada línea\n println(line)\n }\n}\n\nObserva useLines(): es una función que garantiza el cierre del recurso después de completar el bloque. Parece mágico, pero funciona como try-with-resources en Java, solo que más corto.
Escritura en un archivo
\nEscribir datos en Kotlin también es intuitivo. Aquí tienes tres opciones:
\n\n// 1. Sobrescribir el archivo\nFile("output.txt").writeText("¡Hola, mundo!")\n\n// 2. Añadir al final del archivo\nFile("output.txt").appendText("Nueva línea\\n")\n\n// 3. Escribir una lista de cadenas\nval list = listOf("línea1", "línea2", "línea3")\nFile("output.txt").writeText(list.joinToString("\\n"))\n\nPor cierto, si trabajas con datos binarios (imágenes, archivos comprimidos), usa writeBytes() y readBytes():
val imageBytes = File("image.png").readBytes()\n// Procesamiento de bytes...\nFile("copy.png").writeBytes(imageBytes)\n\nGestión del sistema de archivos: creación, eliminación, movimiento
\n\nKotlin no reinventa la rueda, pero hace que trabajar con el sistema de archivos sea más cómodo. Todas las operaciones están disponibles a través de la clase java.io.File con extensiones.
Creación de directorios
\nPara crear un directorio (y todos los padres si no existen):
\n\nval dir = File("data/logs/2024")\nval created = dir.mkdirs() // Devuelve true si se creó\nprintln("Directorio creado: $created")\n\nObserva: mkdir() crea solo la última carpeta, mientras que mkdirs() crea toda la cadena.
Verificación de existencia y eliminación
\n\nval file = File("temp.txt")\nif (file.exists()) {\n if (file.delete()) {\n println("Archivo eliminado")\n } else {\n println("No se pudo eliminar")\n }\n}\n\n// Eliminación recursiva de un directorio\nFile("data").deleteRecursively()\n\nTen cuidado con deleteRecursively(): es una operación irreversible. Verifica dos veces que estás eliminando los datos correctos.
Movimiento y copia
\n\nval source = File("old.txt")\nval target = File("new_dir/new.txt")\n\n// Movimiento (re