Zarábaj až 6 000 € mesačne! Akreditované rekvalifikačné kurzy od 0 €. Viac informácií.

3. diel - Práca s textovými súbormi v Kotlin

V minulom dieli, Triedy pre prácu so súbormi v Kotlin , sme si ukázali, ako fungujú prístupové práva v operačných systémoch a ako sa vytvárajú inštancie tried Path a File.

V dnešnom Kotline tutoriále si vysvetlíme prácu s textovými súbormi. Ukážeme si opäť, ako môžeme využiť obe API Javy, teda staršie java.io.* a novšie java.nio.*.

Najjednoduchšou cestou, ako uložiť dáta aplikácie na pevný disk, je využiť textové súbory. So súbormi s príponou .txt sme sa určite všetci už stretli. Text je v nich uložený jednoducho na jednotlivých riadkoch. Na oddelenie riadkov sa využívajú špeciálne znaky, ktoré sú bohužiaľ špecifické pre každý operačný systém. Toto však za nás našťastie vyrieši Kotlin.

API java.io

Poďme sa najskôr pozrieť na starší spôsob práce so súbormi pomocou java.io.*.

Zápis do nového textového súboru

Vytvoríme si nový projekt s názvom TextoveSoubory. Na zápis do textového súboru slúži trieda FileWriter, ktorá sa ale obvykle obaľuje do triedy BufferedWriter. Objekt BufferedWriter používa na zápis na disk vyrovnávaciu pamäť a je teda výrazne výkonnejší. Tiež poskytuje metódu newLine(). Táto metóda vloží do súboru správny znak konca riadka, nezávisle na operačnom systéme.

Najprv si ale vytvoríme inštanciu triedy File, tak ako sme si to ukázali v lekcii Triedy pre prácu so súbormi. Súbor pomenujeme napríklad oldapi.txt:

val file = File(System.getProperty("user.home") + File.separator + "itnetwork" + File.separator + "oldapi.txt")
file.parentFile
    .mkdirs()

Teraz vytvoríme blok try-with-resources av ňom novú inštanciu typu BufferedWriter. Ako už vieme z predchádzajúcich dielov, blok try-with-resources sa nám automaticky postará o zatvorenie súboru po dokončení zápisu/čítania. Do konštruktora vložíme inštanciu objektu FileWriter. Samotný objekt FileWriter potrebuje objekt typu File, ktorý sme vytvorili vyššie.

try {
     BufferedWriter(FileWriter(file)).use { bw ->

     }
 } catch (e: Exception) {
     println("Do souboru se nepovedlo zapsat.")
 }

Náš objekt BufferedWriter je teraz nasmerovaný na správny súbor. Nový riadok zapíšeme pomocou metódy write(). Odriadkovanie v súbore docielime metódou newLine(). Po dokončení zápisu musíme zavolať metódu flush(), ktorá sa stará o vyprázdnenie bufferu. S tým sa tu nebudeme zaťažovať, postačí nám vedieť, že nami zapísané riadky môžu zostať chvíľu vo vyrovnávacej pamäti a my pomocou flush() vynútime ich zápis.

Kód sa nám teda rozrástol a vyzerá takto:

val file = File(System.getProperty("user.home") + File.separator + "itnetwork" + File.separator + "oldapi.txt")
file.parentFile
    .mkdirs()

try {
    BufferedWriter(FileWriter(file)).use { bw ->
        bw.write("První řádek")
        bw.newLine()
        bw.write("Tento text je na druhém řádku")
        bw.newLine()
        bw.write("A do třetice.")
        bw.newLine()
        bw.flush()
        println("Do souboru bylo zapsáno")
    }
} catch (e: Exception) {
    println("Do souboru se nepovedlo zapsat.")
}

Po spustení sa vytvorí súbor oldapi.txt v našom domovskom adresári v podadresári itnetwork\. Môžeme sa tam pozrieť a bežným textovým editorom sa presvedčiť, že skutočne obsahuje náš text:

Súbory a práce s nimi v Kotlin

Pripísanie textu do existujúceho súboru

Takto do existujúceho súboru pripíšeme nový riadok:

try {
    BufferedWriter(FileWriter(file, true)).use { bw ->
        bw.write("Připsaný řádek")
        bw.newLine()
        bw.flush()
        println("Do souboru bylo připsáno")
    }
} catch (e: Exception) {
    println("Do souboru se nepovedlo zapsat.")
}

Druhým parametrom konštruktora objektu FileWriter s hodnotou true, špecifikujeme pripísanie do existujúceho súboru, ktorého pôvodný obsah zostane nezmenený.

Čítanie existujúceho súboru

Zostáva nám už len vedieť súbor načítať. Nie je to o nič zložitejšie, než zápis a opäť k tomu máme v Jave pripravenú triedu, konkrétne BufferedReader. Použitie je obdobné, namiesto metódy write() použijeme metódu readLine(), ktorá vracia riadok textu zo súboru a zároveň sa presunie na nasledujúci riadok. Budeme ju teda volať v cykle while. Podmienka pre ošetrenie vyjdenia zo súboru je možno krkolomnejšia, kontrolujeme, či prebehlo priradenie nového riadka do premennej.

Kód na výpis obsahu súboru do konzoly vyzerá takto:

try {
    BufferedReader(FileReader(file)).use { br ->
        var s: String?
        while (br.readLine().also { s = it } != null) {
            println(s)
        }
    }
} catch (e: Exception) {
    println("Chyba při čtení ze souboru.")
}

Kód celého nášho programu vyzerá takto:

// zápis do souboru
    val file = File(System.getProperty("user.home") + File.separator + "itnetwork" + File.separator + "oldapi.txt")
    file.parentFile
        .mkdirs()

    try {
        BufferedWriter(FileWriter(file)).use { bw ->
            bw.write("První řádek")
            bw.newLine()
            bw.write("Tento text je na druhém řádku")
            bw.newLine()
            bw.write("A do třetice.")
            bw.newLine()
            bw.flush()
            println("Do souboru bylo zapsáno")
        }
    } catch (e: Exception) {
        println("Do souboru se nepovedlo zapsat.")
    }

    // připsání textu do existujícího souboru
    try {
        BufferedWriter(FileWriter(file, true)).use { bw ->
            bw.write("Připsaný řádek")
            bw.newLine()
            bw.flush()
            println("Do souboru bylo připsáno")
        }
    } catch (e: Exception) {
        println("Do souboru se nepovedlo zapsat.")
    }

    // výpis obsahu souboru
    println("Vypisuji celý soubor:")
    try {
        BufferedReader(FileReader(file)).use { br ->
            var s: String?
            while (br.readLine().also { s = it } != null) {
                println(s)
            }
        }
    } catch (e: Exception) {
        println("Chyba při čtení ze souboru.")
    }

A výsledok:

Do souboru bylo zapsáno
Do souboru bylo připsáno
Vypisuji celý soubor:
První řádek
Tento text je na druhém řádku
A do třetice.
Připsaný řádek

API java.nio

Teraz sa pozrieme na novší spôsob práce so súbormi pomocou java.nio.*.

Zápis do nového textového súboru

Najprv si vytvoríme inštanciu triedy Path. Súbor pomenujeme napríklad newapi.txt:

val path = Path.of(System.getProperty("user.home"), "itnetwork", "newapi.txt")

Na zápis do súboru použijeme statickú metódu writeString() z triedy Files. Nezabudneme najskôr vytvoriť všetky potrebné adresáre a zachytávať prípadnú výnimku. Ako oddeľovač riadku použijeme univerzálny oddeľovač pomocou metódy lineSeparator().

Metóda writeString() prijíma dva a viac parametrov. Prvý parameter je typu Path, čiže súbor, do ktorého chceme zapisovať. Druhý parameter je typu String, čiže text, ktorý chceme zapisovať. Potom nasledujú nepovinné parametre typu StandardOpenOption, ktorými metóde hovoríme, akým spôsobom sa má súbor otvoriť.

Spôsoby otvorenia súboru

Najpoužívanejšie voľby výpočtového typu StandardOpenOption pre spôsoby otvorenia súboru sú tieto:

  • CREATE - vytvorí nový súbor, nevyhadzuje chybu, ak už existuje,
  • CREATE_NEW - vytvorí nový súbor, vyhodí chybu, ak súbor už existuje,
  • TRUNCATE_EXISTING - pri otvorení vymaže obsah súboru,
  • APPEND - otvorí súbor na pridávanie obsahu.
V nasledujúcom príklade pri zápise prvého riadku použijeme voľbu CREATE a TRUNCATE_EXISTING, aby sa súbor vytvoril a existujúci súbor najskôr vymazal. Každý ďalší zápis už robíme pomocou voľby APPEND, aby sa zapisovaný text typu String pridal na koniec súboru:
try {
    Files.createDirectories(path.parent)
    Files.writeString(
        path,
        "První řádek" + System.lineSeparator(),
        StandardOpenOption.CREATE,
        StandardOpenOption.TRUNCATE_EXISTING
    )

} catch (ex: IOException) {
    println("Chyba při zápisu do souboru: " + ex.message)
}

Rovnako ako v prípade staršieho API java.io, sa nám aj teraz po spustení programu vytvorí nový súbor s názvom newapi.txt obsahujúci tri riadky textu. Môžeme si to overiť ľubovoľným textovým editorom.

Pripísanie textu do existujúceho súboru

Pripísanie riadkov do už existujúceho súboru robíme pomocou voľby APPEND:

try {
    Files.writeString(path, "Tento text je na druhém řádku" + System.lineSeparator(), StandardOpenOption.APPEND)
        Files.writeString(path, "A do třetice" + System.lineSeparator(), StandardOpenOption.APPEND)
    } catch (IOException ex) {
    System.out.println("Chyba pri zápise do súboru: " + ex.message());
}

Čítanie existujúceho súboru

Na čítanie riadkov z textového súboru použijeme metódu readAllLines() opäť z triedy Files. Táto metóda vracia kolekciu List<String>:

try {
    val lines = Files.readAllLines(path)
    lines.forEach { x: String? -> println(x) }
} catch (ex: IOException) {
    println("Chyba pri čítaní súboru: " + ex.message)
}

Novovytvorený súbor newapi.txt opäť nájdeme v domovskom adresári v podadresári itnetwork\ a presvedčíme sa, že skutočne obsahuje náš text.

V nasledujúcej lekcii, Práca s CSV súbormi v Kotlin - Načítanie objektov , dokončíme našu objektovú formulárovú aplikáciu s databázou používateľov s použitím textových súborov vo formáte CSV.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 6x (6.9 MB)
Aplikácia je vrátane zdrojových kódov v jazyku Kotlin

 

Predchádzajúci článok
Triedy pre prácu so súbormi v Kotlin
Všetky články v sekcii
Súbory a práce s nimi v Kotlin
Preskočiť článok
(neodporúčame)
Práca s CSV súbormi v Kotlin - Načítanie objektov
Článok pre vás napísal Filip Studený
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
.
Aktivity