File.forEachLine în Kotlin

Fișiere (kotlin.io) Kotlin 1.0 (JVM)

Parcurg un fișier rând cu rând, fără să-l încarce tot în memorie; fișierul se închide automat la final.

Sintaxă
fun File.forEachLine(charset: Charset = Charsets.UTF_8, action: (line: String) -> Unit)
inline fun <T> File.useLines(charset: Charset = Charsets.UTF_8, block: (Sequence<String>) -> T): T

Ce face File.forEachLine

forEachLine { rand -> ... } citește fișierul câte un rând și rulează blocul pentru fiecare. În memorie stă doar rândul curent, deci funcționează și cu fișiere foarte mari. La final fișierul este închis automat.

useLines { randuri -> ... } îți dă rândurile ca o Sequence<String>, pe care poți aplica filter, map, count sau first. Blocul poate returna o valoare, care devine rezultatul lui useLines. Fișierul se închide când blocul se termină, așa că nu păstra secvența pentru mai târziu: transformă ce ai nevoie în rezultat (de exemplu cu toList()) chiar în bloc.

Parametri

Parametru Descriere
action Pentru forEachLine: ce se face cu fiecare rând.
block Pentru useLines: blocul care primește secvența de rânduri și returnează un rezultat.

Ce returnează

forEachLine: nimic. useLines: valoarea returnată de bloc.

Exemple

Exemplul 1: Numerotarea rândurilor cu forEachLine

Fiecare rând este afișat imediat după ce este citit.

import java.io.File

fun main() {
    File("poezie.txt").writeText("Somnoroase păsărele\nPe la cuiburi se adună,\nSe ascund în rămurele\n")
    var nr = 0
    File("poezie.txt").forEachLine { rand ->
        nr++
        println("$nr. $rand")
    }
}

Rezultat

1. Somnoroase păsărele
2. Pe la cuiburi se adună,
3. Se ascund în rămurele

Exemplul 2: Numărarea erorilor dintr-un jurnal cu useLines

Secvența este filtrată și numărată în bloc; useLines returnează numărul.

import java.io.File

fun main() {
    val jurnal = File("aplicatie.log")
    jurnal.writeText("INFO pornit\nEROARE conexiune\nINFO cerere\nEROARE disc plin\nINFO oprit\n")
    val erori = jurnal.useLines { randuri -> randuri.count { it.startsWith("EROARE") } }
    println("Erori: $erori")
}

Rezultat

Erori: 2

Exemplul 3: Primele rânduri care se potrivesc

Secvența se citește doar cât e nevoie: după primele două potriviri, citirea se oprește.

import java.io.File

fun main() {
    File("comenzi.txt").writeText("Ana 120\nIon 45\nMaria 300\nDan 80\nEla 250\n")
    val mari = File("comenzi.txt").useLines { randuri ->
        randuri.filter { it.substringAfter(" ").toInt() > 100 }.take(2).toList()
    }
    println(mari)
}

Rezultat

[Ana 120, Maria 300]

Greșeli frecvente

  • Returnezi secvența din useLines și o folosești după bloc. Fișierul este deja închis și apare o eroare; transformă rezultatul cu toList() în interior.
  • Folosești readLines() pentru un fișier de jurnal de mai mulți GB. Citirea rând cu rând cu useLines nu încarcă tot fișierul.

Comenzi înrudite

  • File.readLines: Citește un fișier text și returnează lista rândurilor, fără caracterele de rând nou.
  • File.bufferedReader: Deschide un fișier pentru citire sau scriere cu buffer; se folosește cu use, ca să fie închis automat.
  • use: Folosește o resursă (fișier, conexiune) într-un bloc și o închide automat la final, chiar dacă apare o excepție.
  • sequence: Construiește o secvență dintr-un bloc de cod care dă valori una câte una cu yield; codul se oprește și continuă la cerere.