Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 4 - Práce s CSV soubory v Kotlin - Uložení objektů

V minulé lekci, Práce s textovými soubory v Kotlin, jsme si ukázali zápis do textových souborů i jejich čtení.

V dnešním Kotlin tutoriálu si vytvoříme formulářovou aplikaci s databází uživatelů, která bude ukládat instance do textových souborů ve formátu CSV. Do CSV (jako Comma Separated Values) souborů ukládáme hodnoty oddělené čárkou, případně středníkem. Každý řádek bude uchovávat hodnoty jednoho uživatele.

JavaFX aplikace

K tvorbě formuláře využijeme framework JavaFX. Jednoduchý formulář pak díky tomu budeme moci naklikat v nástroji Scene Builder, který za nás vygeneruje XML kód. Zájemce odkážu na kurz v sekci Java, kde je sice jako vývojové prostředí použito NetBeans, ale postup v IntelliJ bude velmi podobný.

Nejprve si založíme v IntelliJ nový Kotlin projekt. V dalším okně vybereme položku JavaFX a doplníme název aplikace. Programovacím jazykem bude Kotlin, správu balíčků necháme na Maven, v políčku Group nastavujeme název package, který jsme přepsali na itnetwork:

screenshot založení projektu - Soubory a práce s nimi v Kotlin

Pokračujeme tlačítkem Next do dalšího okna, ve kterém nic měnit nebudeme a pouze klikneme na tlačítko Create.

IntelliJ nám vygenerovalo a otevřelo soubor pom.xml, jeden .fxml soubor pro vzhled formuláře, k němu kontroler a hlavní třídu, vše ve stylu "Hello world" aplikací.

Konfigurační soubor pom.xml měnit nebudeme, ostatní si můžeme smazat a postupně nahradit vlastními, případně si je přejmenujeme a upravíme jejich obsah.

Zaměřme se ale nejdříve na logickou vrstvu aplikace.

Třída Uzivatel

Pojďme se shodnout na tom, jak bude naše třída uživatele vypadat. Následně si ukážeme, jak její instance do CSV uložíme.

Do vytvořeného projektu si přidáme třídu Uzivatel. U uživatele budeme evidovat jeho jméno, věk a datum, kdy byl registrován. Konstruktor bude instanci inicializovat na základě těchto tří vlastností. Přepíšeme si metodu toString() tak, aby vrátila jméno uživatele. Třída tedy bude vypadat takto:

class Uzivatel(val jmeno: String, val vek: Int, val registrovan: LocalDate) {

    override fun toString(): String {
        return jmeno
    }
}

Naimportujeme si balíček java.time.LocalDate.

Třída Databáze

Třídu uživatele Uzivatel máme. Vytvoříme si i třídu pro naši databázi, kterou nazveme Databaze. Ta bude obsahovat kolekci uživatelů, které budeme ukládat do generického mutableListOf<Uzivatel>. Kolekce bude privátní a přidávání uživatelů (případně jejich mazání, vyhledávání a podobně) bude realizováno veřejnými metodami. Databáze bude obsahovat metody k načtení CSV souboru, a také k uložení obsahu databáze do souboru. Pro jméno souboru budeme mít privátní atribut soubor ve třídě Databaze.

Přidejme si tedy k projektu třídu Databaze a předepišme si do ní i zmíněné metody:

class Databaze(soubor: Path) {
    private val uzivatele = mutableListOf<Uzivatel>()
    private val soubor: Path

    init {
        this.soubor = soubor
    }

    fun pridejUzivatele(jmeno: String, vek: Int, registrovan: LocalDate) {

    }

    fun vratVsechny(): List<Uzivatel> {

    }

    val model: MutableList<Uzivatel>


    @Throws(IOException::class)
    fun uloz() {

    }

    @Throws(IOException::class)
    fun nacti() {

    }
}

IntelliJ nám u metody vratVsechny() vyhubuje, protože nevrací hodnotu, ale toho si zatím nebudeme všímat. Jednotlivé metody vzápětí postupně naimplementujeme.

Metoda pridejUzivatele()

Pojďme si ukázat, jak budou uživatelé ve formátu CSV vypadat. Každý řádek bude reprezentovat jednoho uživatele. Vlastnosti uživatele budou odděleny středníky.

Například uživatel Pavel Slavík, kterému je 22 let a zaregistroval se 21.3.2000 by ve formátu CSV vypadal takto:

Pavel Slavík;22;21.3.2000

Na první pohled vidíme, že je soubor relativně jednoduše čitelný, i když nezasvěcený se může jen domnívat, co je číslo 22 a k čemu se váže ono datum. V souboru může být samozřejmě více uživatelů, tedy více řádků.

Přidáme si metodu pridejUzivatele():

fun pridejUzivatele(jmeno: String, vek: Int, registrovan: LocalDate) {
    uzivatele.add(Uzivatel(jmeno, vek, registrovan))
}

Metoda getModel()

Dále si přidáme metodu model(), která vrátí kolekci uživatelů:

val model: MutableList<Uzivatel>
    get() = uzivatele

Metoda vratVsechny()

Nakonec si napíšeme metodu vratVsechny(), která nám vrátí kolekci uživatelů List<Uzivatel>:

fun vratVsechny(): List<Uzivatel> {
    return uzivatele
}

Uložení uživatelů do CSV

Nyní se již dostáváme k práci s CSV souborem. Proiterujeme náš list uživatelů a pro každého uživatele vytvoříme proměnnou radek typu String, ve které budou jednotlivé vlastnosti uživatele oddělené středníkem. Obsah proměnné radek pak zapíšeme do souboru soubor:

@Throws(IOException::class)
fun uloz() {
    // Nejprve soubor vytvoříme, pokud již existuje tak jej vyprázdníme.
    Files.writeString(soubor, "", StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)
    for (u in vratVsechny()) {
        val radek: String =
            u.jmeno + ";" + u.vek + ";" + u.registrovan.toString() + System.lineSeparator()
        Files.writeString(soubor, radek, StandardOpenOption.APPEND)
    }
}

FXML formulář

Nyní budeme potřebovat vytvořit samotný formulář. FXML soubory ukládáme ve složce main/ do podsložky resource/ a vnořeného balíčku. Na ten klikneme pravým tlačítkem myši a přidáme novou položku FXML File s názvem formular.fxml. Soubor si najdeme ve svém počítači a otevřeme jej v Scene Builderu.

Prozatím do něj vložíme kontejner VBox a do něj přidáme jeden Label a jeden Button. Kontejneru ve vlastnostech nastavíme centrování na střed, a v nabídce Controller vyplníme název kontroleru: itnetwork.uzivatele.DatabazeKontroler. Položce Label vymažeme defaultní text a do fx:id vyplníme errorText, aby se nám zde zobrazovaly případné chybové hlášky. Button necháme zobrazovat text Ulož a v nabídce Code vyplníme políčko On Action textem uloz. Tím zajistíme, že po kliknutí na tlačítko bude zavolána metoda uloz().

Máme hotovo, změny uložíme a vrátíme se do IntelliJ.

Kontroler DatabazeKontroler

Do projektu přidáme další Kotlin třídu DatabazeKontroler. V té vytvoříme privátní atribut databaze, do kterého v konstruktoru formuláře uložíme novou instanci naší databáze:

class DatabazeKontroler {

    private var databaze: Databaze? = null

    init {
        try {
            val path = Path.of(System.getProperty("user.home"), "itnetwork", "uzivatele.csv")
            Files.createDirectories(path.getParent())
            databaze = Databaze(path)
        } catch (ex: IOException) {
            Logger.getLogger(DatabazeKontroler::class.java.name).log(Level.SEVERE, null, ex)

        }
    }
}

Pokud vám IntelliJ podtrhne poslední řádek, otevřete si soubor modules-info.java a doplňte do něj řádek requires java.logging;, kterým zavoláte potřebný modul.

Dále si doplníme obsluhu formuláře:

@FXML
private lateinit var errorText: Label

Nejprve deklarujeme privátní proměnnou errorText pro zobrazení chybových hlášek v naší Label komponentě.

Dále doplníme obsluhu tlačítka Ulož, které zajistí uložení dvou níže uvedených uživatelů. Toto řešení je provizorní, abychom mohli vše vyzkoušet, později bude aplikace vypadat lépe. Dále celou databázi metoda uloz() uloží do souboru:

@FXML
private fun uloz() {
    try {
        databaze!!.pridejUzivatele("Pavel Slavík", 22, LocalDate.of(2000, 3, 21))
        databaze!!.pridejUzivatele("Jan Novák", 31, LocalDate.of(2012, 10, 30))
        databaze!!.uloz()

    } catch (ex: IOException) {
        errorText.text = "Databázi se nepodařilo uložit, zkontrolujte přístupová práva k souboru."
        println("Databázi se nepodařilo uložit, zkontrolujte přístupová práva k souboru.")
    }
}

Položky k obsluze FXML formuláře nezapomeneme označit anotací @FXML.

Hlavní třída

Na závěr nám dnes zbývá doplnit hlavní třídu s main() metodou. Její kód bude dost podobný vygenerované třídě HelloApplication. My si třídu nazveme Main.kt a doplníme kód:

class Aplikace : Application() {
    override fun start(stage: Stage) {
        val fxmlLoader = FXMLLoader(Aplikace::class.java.getResource("formular.fxml"))
        val scene = Scene(fxmlLoader.load(), 320.0, 240.0)
        stage.title = "Databáze uživatelů!"
        stage.scene = scene
        stage.show()
    }
}

fun main() {
    Application.launch(Aplikace::class.java)
}

V hlavní třídě voláme pomocí fxmlLoader patřičný formulář, nastavujeme jeho velikost a titulek a necháme vše zobrazit.

Testování

Aplikaci spustíme a klikneme na tlačítko. Nyní otevřeme (např. v NotePadu) soubor uzivatele.csv a vidíme, že má následující obsah:

Pavel Slavík;22;21.3.2000
Jan Novák;31;30.10.2012

Vše tedy funguje, jak má :).

V příští lekci, Práce s CSV soubory v Kotlin - Načtení objektů, dokončíme naši objektovou formulářovou aplikaci s databází uživatelů s použitím textových souborů ve formátu CSV.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 7x (35.43 kB)
Aplikace je včetně zdrojových kódů v jazyce Kotlin

 

Předchozí článek
Práce s textovými soubory v Kotlin
Všechny články v sekci
Soubory a práce s nimi v Kotlin
Přeskočit článek
(nedoporučujeme)
Práce s CSV soubory v Kotlin - Načtení objektů
Článek pro vás napsal Filip Studený
Avatar
Uživatelské hodnocení:
3 hlasů
.
Aktivity