4. diel - Práca s CSV súbormi v Kotlin - Uloženie objektov
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 vytvoríme formulárovú aplikáciu s databázou užívateľov, ktorá bude ukladať inštancie do textových súborov vo formáte CSV. Do CSV (ako Comma Separated Values) súborov ukladáme hodnoty oddelené čiarkou, prípadne bodkočiarkou. Každý riadok bude uchovávať hodnoty jedného používateľa.
JavaFX aplikácie
Na tvorbu formulára využijeme framework JavaFX. Jednoduchý formulár potom vďaka tomu budeme môcť naklikať v nástroji Scene Builder, ktorý za nás vygeneruje XML kód. Záujemca odkážem na kurz v sekcii Java, kde je síce ako vývojové prostredie použité NetBeans, ale postup v IntelliJ bude veľmi podobný.
Najprv si založíme v IntelliJ nový Kotlin projekt. V ďalšom okne
vyberieme položku JavaFX a doplníme názov aplikácie. Programovacím
jazykom bude Kotlin, správu balíčkov necháme na Maven, v
políčku Group nastavujeme názov package, ktorý sme
prepísali na itnetwork
:
Pokračujeme tlačidlom Next do ďalšieho okna, v ktorom nič meniť nebudeme a iba klikneme na tlačidlo Create.
IntelliJ nám vygenerovalo a otvorilo súbor pom.xml
, jeden
.fxml
súbor pre vzhľad formulára, k nemu kontrolér a hlavnú
triedu, všetko v štýle "Hello world" aplikácií.
Konfiguračný súbor pom.xml
meniť nebudeme,
ostatní si môžeme zmazať a postupne nahradiť vlastnými, prípadne si ich
premenujeme a upravíme ich obsah.
Zamerajme sa ale najskôr na logickú vrstvu aplikácie.
Trieda Uzivatel
Poďme sa zhodnúť na tom, ako bude naša trieda používateľa vyzerať. Následne si ukážeme, ako jej inštancie do CSV uložíme.
Do vytvoreného projektu si pridáme triedu Uzivatel
. U
užívateľa budeme evidovať jeho meno, vek a
dátum, kedy bol registrovaný. Konštruktor bude inštanciu
inicializovať na základe týchto troch vlastností.
Prepíšeme si metódu toString()
tak, aby vrátila meno
používateľa. Trieda teda bude vyzerať 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
.
Trieda Databáze
Triedu užívateľa Uzivatel
máme. Vytvoríme
si aj triedu pre našu databázu, ktorú nazveme
Databaze
. Tá bude obsahovať kolekciu
užívateľov, ktoré budeme ukladať do generického
mutableListOf<Uzivatel>
. Kolekcia bude
privátna a pridávanie užívateľov (prípadne ich mazanie,
vyhľadávanie a podobne) bude realizované verejnými
metódami. Databáza bude obsahovať metódy na
načítanie CSV súboru, a tiež na uloženie
obsahu databázy do súboru. Pre meno súboru budeme
mať privátny atribút soubor
v triede Databaze
.
Pridajme si teda k projektu triedu Databaze
a predpíšme si do
nej aj spomínané metódy:
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 pri metóde vratVsechny()
vyhubuje, pretože nevracia hodnotu, ale to si zatiaľ nebudeme všímať.
Jednotlivé metódy vzápätí postupne naimplementujeme.
Metóda pridejUzivatele()
Poďme si ukázať, ako budú používatelia vo formáte CSV vyzerať. Každý riadok bude reprezentovať jedného používateľa. Vlastnosti užívateľa budú oddelené bodkočiarkami.
Napríklad užívateľ Pavel Slavík, ktorý má 22 rokov a zaregistroval sa 21.3.2000 by vo formáte CSV vyzeral takto:
Pavel Slavík;22;21.3.2000
Na prvý pohľad vidíme, že je súbor relatívne jednoducho
čitateľný, aj keď nezasvätený sa môže len domnievať, čo je číslo
22
a na čo sa viaže ono dátum. V súbore môže byť samozrejme
viac používateľov, teda viac riadkov.
Pridáme si metódu pridejUzivatele()
:
fun pridejUzivatele(jmeno: String, vek: Int, registrovan: LocalDate) {
uzivatele.add(Uzivatel(jmeno, vek, registrovan))
}
Metóda getModel()
Ďalej si pridáme metódu model()
, ktorá vráti
kolekciu užívateľov:
val model: MutableList<Uzivatel> get() = uzivatele
Metóda vratVsechny()
Nakoniec si napíšeme metódu vratVsechny()
, ktorá nám vráti
kolekciu užívateľov List<Uzivatel>
:
fun vratVsechny(): List<Uzivatel> { return uzivatele }
Uloženie užívateľov do CSV
Teraz sa už dostávame k práci s CSV súborom.
Preiterujeme náš list užívateľov a pre každého užívateľa vytvoríme
premennú radek
typu String
, v ktorej budú
jednotlivé vlastnosti užívateľa oddelené bodkočiarkou.
Obsah premennej radek
potom zapíšeme do súboru
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ár
Teraz budeme potrebovať vytvoriť samotný formulár. FXML súbory ukladáme
v zložke main/
do podzložky resource/
a vnoreného
balíčka. Na ten klikneme pravým a pridáme novú položku FXML File
s názvom formular.fxml
. Súbor si nájdeme vo svojom počítači a
otvoríme ho v Scene Builderi.
Zatiaľ do neho vložíme kontajner VBox
a do neho pridáme
jeden Label
a jeden Button
. Kontajnera vo
vlastnostiach nastavíme centrovanie na stred, av ponuke Controller
vyplníme názov kontroléra:
itnetwork.uzivatele.DatabazeKontroler
. Položke Label
vymažeme defaultný text a do fx:id
vyplníme
errorText
, aby sa nám tu zobrazovali prípadné chybové hlášky.
Button
necháme zobrazovať text Ulož
av ponuke
Code vyplníme políčko On Action textom uloz
.
Tým zaistíme, že po kliknutí na tlačidlo bude zavolaná metóda
uloz()
.
Máme hotovo, zmeny uložíme a vrátime sa do IntelliJ.
Kontroler
DatabazeKontroler
Do projektu pridáme ďalší Kotlin triedu DatabazeKontroler
. V
tej vytvoríme privátny atribút databaze
, do ktorého v
konštruktore formulára uložíme novú inštanciu našej databázy:
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) } } }
Pokiaľ vám IntelliJ podčiarkne posledný riadok, otvorte si
súbor modules-info.java
a doplňte doň riadok
requires java.logging;
, Ktorým zavoláte potrebný modul.
Ďalej si doplníme obsluhu formulára:
@FXML private lateinit var errorText: Label
Najprv deklarujeme privátnu premennú errorText
na zobrazenie
chybových hlášok v našom Label
komponente.
Ďalej doplníme obsluhu tlačidla Ulož, ktoré zaistí uloženie
dvoch nižšie uvedených užívateľov. Toto riešenie je
provizórne, aby sme mohli všetko vyskúšať, neskôr bude aplikácia vyzerať
lepšie. Ďalej celú databázu metóda uloz()
uloží do
súboru:
@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 na obsluhu FXML formulára nezabudneme označiť
anotáciou @FXML
.
Hlavná trieda
Na záver nám dnes zostáva doplniť hlavnú triedu s main()
metódou. Jej kód bude dosť podobný vygenerovanej triede
HelloApplication
. My si triedu 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 hlavnej triede voláme pomocou fxmlLoader
patričný
formulár, nastavujeme jeho veľkosť a titulok a necháme všetko
zobraziť.
Testovanie
Aplikáciu spustíme a klikneme na tlačidlo. Teraz otvoríme (napr. v
NotePade) súbor uzivatele.csv
a vidíme, že má nasledujúci
obsah:
Pavel Slavík;22;21.3.2000 Jan Novák;31;30.10.2012
Všetko teda funguje, ako má:) .
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é 7x (35.43 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Kotlin