Lectura y escritura de archivos
Anteriormente, cuando nos referimos a la biblioteca estándar de Kotlin para trabajar con flujos de entrada y salida (Input/Output), nos centramos en la transferencia de datos en consola, y ahora vamos a ver cómo trabajar con archivos, y concretamente algunas maneras para leer y escribir sobre ellos.
Lectura de archivos
Antes de entrar en materia, lógicamente necesitamos un archivo para leer; si estamos trabajando con IntelliJ IDEA, podemos crear desde allí un nuevo directorio y crear nuestro archivo de pruebas. Para tener nuestro proyecto ordenado, es habitual llamar a este directorio resources (recursos) y crear dentro de él otros directorios para, por ejemplo, contener imágenes o archivos de texto del proyecto. Para eso, nos situamos sobre la carpeta principal del proyecto y con el botón secundario del ratón seleccionamos New --> Directory:En la siguiente ventana le asignamos un nombre, en este caso, 'resources' (opcionalmente también podemos marcar este directorio desde Mark directory as --> Resources Root), y ahora sobre esta carpeta recién creada repetimos los pasos para crear otro directorio llamado 'txt'. Finalmente, sobre la carpeta 'txt' seleccionamos New --> File y le asignamos un nombre y una extensión:
Ahora tenemos abierto en IntelliJ IDEA el archivo recién creado y escribimos en él cualquier cosa o pegamos un texto, y guardamos los cambios. Para esta entrada y a modo de ejemplo se utiliza el siguiente texto:
Kotlin Doc comparte y divulga en español información y ejemplos sobre programación con Kotlin y Android. Kotlin es un lenguaje de programación: - Moderno, conciso y seguro - Que combina programación funcional y orientada a objetos - De código abierto - Interoperable con JAVA - Divertido de aprender y de escribir
Ahora seleccionando el nuevo archivo podemos ir a Copy relative Path para obtener su ruta relativa, en mi caso: resources/txt/archivo
El paquete kotlin.io ofrece varias maneras de acceder al texto de un archivo, como InputStream, BufferedReader y File, aunque finalmente todas ellas utilizan la extensión java.io.File.
InputStream
import java.io.File import java.io.InputStream fun main() { val inputStream: InputStream = File("resources/txt/archivo").inputStream() val inputString = inputStream.bufferedReader().use { it.readText() } println(inputString) // muestra en consola todo el archivo }
Otra opción:
import java.io.File import java.io.InputStream import java.nio.charset.Charset fun main() { val pathName = "resources/txt/archivo" val miArchivo = File(pathName) val inputStream: InputStream = miArchivo.inputStream() val contenido = inputStream.readBytes().toString(Charset.defaultCharset()) println(contenido) // muestra en pantalla todo el archivo }
En los dos ejemplos anteriores se crea un InputStream desde un File, con la diferencia de que en el primer caso el contenido se lee con bufferedReader y readText, y en el segundo ejemplo con readBytes y luego los bytes se transforman a texto (String).
Podemos también leer línea por línea:
import java.io.File import java.io.InputStream fun main() { val inputStream: InputStream = File("resources/txt/archivo").inputStream() val lineas = mutableListOf<String>() inputStream.bufferedReader().useLines { lines -> lines.forEach { lineas.add(it) } } var n = 1 lineas.forEach { println("${n++} " + it) } // imprime todo el archivo numerando cada línea }
BufferedReader
import java.io.BufferedReader import java.io.File fun main() { val bufferedReader: BufferedReader = File("resources/txt/archivo").bufferedReader() val inputString = bufferedReader.use { it.readText() } println(inputString) // muestra todo el archivo }
Y para leer línea por línea con BufferedReader:
import java.io.BufferedReader import java.io.File fun main() { val bufferedReader: BufferedReader = File("resources/txt/archivo").bufferedReader() val lineas = mutableListOf<String>() bufferedReader.useLines { lines -> lines.forEach { lineas.add(it) } } lineas.forEach { println("> $it") } }
File
Posiblemente una de las formas más comunes de leer un archivo con Kotlin es usando directamente File con readText:import java.io.File fun main() { val pathName = "resources/txt/archivo" val miArchivo = File(pathName) val contenido = miArchivo.readText() println(contenido) }
Un ejemplo de File con readLines y useLines:
import java.io.File fun main() { val pathName = "resources/txt/archivo" val miArchivo = File(pathName) val lineas = miArchivo.readLines() lineas.forEach { println(it) } // muestra todo el archivo val lineasLista = mutableListOf<String>() miArchivo.useLines { lines -> lines.forEach { lineasLista.add(it) } } lineasLista.forEach { println(it) } // muestra todo el archivo lineasLista.forEachIndexed { i, line -> println("$i $line") } // numera cada línea }
Y ahora un ejemplo de Files con readBytes, que lee todo el contenido de un archivo como una matriz de bytes (no se recomienda en archivos grandes), y mostramos el resultado en líneas de diez números:
import java.io.File fun main() { val pathName = "resources/txt/archivo" val miArchivo = File(pathName) val bytes: ByteArray = miArchivo.readBytes() bytes.forEachIndexed { i, byte -> when { i <= 10 && i != 9 -> print("$byte ") i.toString().endsWith("9") -> print("$byte \n") else -> print("$byte ") } } }
Escritura de archivos
Al igual que para leer archivos, la extensión java.io.File del paquete kotlin.io ofrece varias maneras de escribir un archivo, por ejemplo con PrintWriter, BufferedWriter, writeText y write.PrintWriter
Podemos crear un archivo en la ruta de nuestro directorio 'resources/txt' de la siguiente manera (printWriter prepara para escribir un archivo y el método use ejecuta el cuerpo de la función en el archivo y luego lo cierra):import java.io.File fun main() { val outString = "Kotlin Doc\nEscribiendo un archivo con printWriter." File("resources/txt/test.txt").printWriter().use { out -> out.println(outString) } }
Otro ejemplo (comprobamos que sobrescribe el archivo anterior):
import java.io.File fun main() { val ruta = "resources/txt/test.txt" val archivo = File(ruta) archivo.printWriter().use { out -> out.println("Primera línea") out.println("Segunda línea") } }
BufferedWriter
import java.io.File fun main() { val outString = "Kotlin Doc\nEscribiendo un archivo con bufferedWriter." File("resources/txt/test.txt").bufferedWriter().use { out -> out.write(outString) } }
Otro ejemplo:
import java.io.File fun main() { val ruta = "resources/txt/test.txt" val archivo = File(ruta) archivo.bufferedWriter().use { out -> out.write("Primera línea\n") out.write("Segunda línea\n") } }
writeText
import java.io.File fun main() { val outString = "Kotlin Doc\nEscribiendo un archivo con writeText." val archivo = File("resources/txt/test.txt") archivo.writeText(outString) archivo.appendText("\nLínea 3.") archivo.appendText("\nLínea 4.") }
write
En el siguiente ejemplo la función Files.write() utiliza tres parámetros: la ruta del archivo, el array de bytes para escribir y por último la opción que especifica cómo se abre el archivo. En este caso con APPEND le decimos que añada el contenido al final sin sobrescribir el archivo, por lo que cada vez que ejecutamos el programa se añade nuevo texto al archivo (otras opciones son CREATE, CREATE_NEW, DELETE_ON_CLOSE, READ, WRITE):import java.io.File import java.nio.file.Files.write import java.nio.file.StandardOpenOption fun main() { val outString = "Kotlin Doc\nEscribiendo un archivo con writeText II." val archivo = File("resources/txt/test.txt") write(archivo.toPath(), outString.toByteArray(), StandardOpenOption.APPEND) }
Comentarios
Publicar un comentario