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:
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.
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