Una delle più comuni fonti di dati con cui si interagisce in un programma è costituita dai file. Come in Java,
anche in Kotlin possono essere letti e scritti con i medesimi meccanismi ma sfruttando, in taluni casi, funzionalità
più comode. Vediamo un caso molto utile che è quello della lettura di file di testo. Supponiamo di averne uno, in formato CSV, contenente dei log
di sistema simile al seguente:
24/02/2019 13:22;AUTH ERR;user klopt23
24/02/2019 13:28;AUTH ERR;user klopt23
24/02/2019 13:32;CONN FAIL;failed connection to 192.168.1.16
24/02/2019 13:34;AUTH ERR;user igor71
24/02/2019 13:41;CONN FAIL;failed connection to 192.168.1.12
Se il suo nome è dati.txt potremmo ottenerne la stampa in output (cambiando opportunamente il percorso) nel
seguente modo:
File("dati.txt").forEachLine { println(it) }
Come si può vedere, si è fatto accesso al file in una maniera molto comoda quasi fosse una lista di oggetti. All'interno
del blocco introdotto da forEachLine potremmo inserire tutto il codice necessario a gestire ogni singola riga.
Esiste anche useLines uan funzionalità che permette di accedere alle righe nel loro complesso. Si potrà usare anche in questo
caso il riferimento it nel blocco di codice ma questa volta esso rappresenterà una sequenza di stringhe. Ciò permetterà di eseguire
operazioni la cui visuale esuli dalla singola riga. Ad esempio, potremmo richiedere di restituire le prime due righe di un file sotto forma di lista di
stringhe:
val primeDue=File("dati.txt").useLines {
it.take(2).toList()
}
In questo caso, l'oggetto primeDue conterrebbe al suo interno due stringhe indicanti la prima e la seconda riga di dati.txt. Altro metodo utile
per scopi simili è readLines, consigliabile però per file di dimensioni non troppo grandi. Se, ad esempio, volessimo stampare
solo le righe contenenti la parola "AUTH" potremmo operare così:
File("dati.txt")
.readLines()
.filter{ it.contains("AUTH")}
.forEach { println(it) }
ottenendo in output questo:
24/02/2019 13:22;AUTH ERR;user klopt23
24/02/2019 13:28;AUTH ERR;user klopt23
24/02/2019 13:34;AUTH ERR;user igor71
L'aspetto interessante di questo metodo è che permette, con grande facilità, di applicare tutti quei funzionamenti
che abbiamo già visto e che derivano dalle Stream API di Java. Come ulteriore esempio, potremmo applicare un doppio filtro
verificando che i messaggi contenenti "AUTH" terminino anche con la stringa "klopt23" ottenendo in questo modo in output
solo le prime due righe:
File("dati.txt")
.readLines()
.filter{ it.contains("AUTH").and(it.endsWith("klopt23"))}
.forEach { println(it) }