Lekce 3 - Práce s textovými soubory v Kotlin
V minulém dílu, Třídy pro práci se soubory v Kotlin, jsme si ukázali, jak fungují přístupová
práva v operačních systémech a jak se vytvářejí instance tříd
Path
a File
.
V dnešním Kotlin tutoriálu si vysvětlíme práci s textovými
soubory. Ukážeme si opět, jak můžeme využít obě API Javy, tedy
starší java.io.*
a novější java.nio.*
.
Nejjednodušší cestou, jak uložit data aplikace na pevný disk, je
využít textové soubory. Se soubory s příponou .txt
jsme se
jistě všichni již setkali. Text je v nich uložen jednoduše na jednotlivých
řádcích. K oddělení řádků se využívá speciálních znaků, které
jsou bohužel specifické pro každý operační systém. Toto však za nás
naštěstí vyřeší Kotlin.
API java.io
Pojďme se nejprve podívat na starší způsob práce se soubory pomocí
java.io.*
.
Zápis do nového textového souboru
Vytvoříme si nový projekt s názvem TextoveSoubory
. K zápisu
do textového souboru slouží třída FileWriter
, která se ale
obvykle obaluje do třídy BufferedWriter
. Objekt
BufferedWriter
používá k zápisu na disk vyrovnávací
paměť a je tudíž výrazně výkonnější. Také poskytuje metodu
newLine()
. Tato metoda vloží do souboru správný znak
konce řádku, nezávisle na operačním systému.
Nejprve si ale vytvoříme instanci třídy File
, tak jak jsme
si to ukázali v lekci Třídy pro práci se
soubory. Soubor pojmenujeme třeba oldapi.txt
:
val file = File(System.getProperty("user.home") + File.separator + "itnetwork" + File.separator + "oldapi.txt") file.parentFile .mkdirs()
Nyní vytvoříme blok try-with-resources
a v něm novou
instanci typu BufferedWriter
. Jak již víme z předchozích
dílů, blok try-with-resources
se nám automaticky postará o
zavření souboru po dokončení zápisu/čtení. Do
konstruktoru vložíme instanci objektu FileWriter
. Samotný objekt
FileWriter
potřebuje objekt typu File
, který jsme
vytvořili výše.
try { BufferedWriter(FileWriter(file)).use { bw -> } } catch (e: Exception) { println("Do souboru se nepovedlo zapsat.") }
Náš objekt BufferedWriter
je nyní nasměrovaný na správný
soubor. Nový řádek zapíšeme pomocí metody
write()
. Odřádkování v souboru docílíme
metodou newLine()
. Po dokončení zápisu musíme zavolat metodu
flush()
, která se stará o vyprázdnění
bufferu. S tím se zde nebudeme zatěžovat, postačí nám vědět,
že námi zapsané řádky mohou zůstat chvíli ve vyrovnávací
paměti a my pomocí flush()
vynutíme jejich
zápis.
Kód se nám tedy rozrostl a vypadá 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 spuštění se vytvoří soubor oldapi.txt
v našem
domovském adresáři v podadresáři itnetwork\
. Můžeme se tam
podívat a běžným textovým editorem se přesvědčit, že opravdu obsahuje
náš text:

Připsání textu do existujícího souboru
Takto do existujícího souboru připíšeme nový řádek:
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 parametrem konstruktoru objektu FileWriter
s hodnotou true
, specifikujeme připsání do existujícího
souboru, jehož původní obsah zůstane nezměněn.
Čtení existujícího souboru
Zbývá nám již jen umět soubor načíst. Není to o nic
složitější, než zápis a opět k tomu máme v Javě připravenou třídu,
konkrétně BufferedReader
. Použití je obdobné, namísto metody
write()
použijeme metodu readLine()
, která vrací
řádek textu ze souboru a zároveň se přesune na řádek
následující. Budeme ji tedy volat v cyklu while
. Podmínka pro
ošetření vyjetí ze souboru je možná krkolomnější, kontrolujeme, zda
proběhlo přiřazení nové řádky do proměnné.
Kód k výpisu obsahu souboru do konzole vypadá 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 našeho programu vypadá 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ýsledek:
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
Teď se podíváme na novější způsob práce se soubory pomocí
java.nio.*
.
Zápis do nového textového souboru
Nejprve si vytvoříme instanci třídy Path
. Soubor pojmenujeme
třeba newapi.txt
:
val path = Path.of(System.getProperty("user.home"), "itnetwork", "newapi.txt")
K zápisu do souboru použijeme statickou metodu writeString()
ze třídy Files
. Nezapomeneme nejprve vytvořit všechny
potřebné adresáře a zachytávat případnou
výjimku. Jako oddělovač řádku použijeme univerzální
oddělovač pomocí metody lineSeparator()
.
Metoda writeString()
přijímá dva a více parametrů.
První parametr je typu Path
, čili
soubor, do kterého chceme zapisovat. Druhý
parametr je typu String
, čili text, který chceme
zapisovat. Poté následují nepovinné parametry typu
StandardOpenOption
, kterými metodě říkáme, jakým způsobem se
má soubor otevřít.
Způsoby otevření souboru
Nejpoužívanější volby výčtového typu StandardOpenOption
pro způsoby otevření souboru jsou tyto:
CREATE
- vytvoří nový soubor, nevyhazuje chybu, pokud už existuje,CREATE_NEW
- vytvoří nový soubor, vyhodí chybu, pokud soubor už existuje,TRUNCATE_EXISTING
- při otevření vymaže obsah souboru,APPEND
- otevře soubor pro přidávání obsahu.
V následujícím příkladu při zápisu prvního řádku použijeme volbu
CREATE
a TRUNCATE_EXISTING
, aby se soubor vytvořil a
existující soubor napřed vymazal. Každý další zápis už děláme pomocí
volby APPEND
, aby se zapisovaný text typu String
přidal na konec souboru:
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) }
Stejně, jako v případě staršího
API java.io
, se nám i nyní po spuštění programu vytvoří
nový soubor s názvem newapi.txt
obsahující
tři řádky textu. Můžeme si to ověřit libovolným
textovým editorem.
Připsání textu do existujícího souboru
Připsání řádků do již existujícího souboru děláme pomocí volby
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 při zápisu do souboru: " + ex.message()); }
Čtení existujícího souboru
Ke čtení řádků z textového souboru použijeme metodu
readAllLines()
opět ze třídy Files
. Tato metoda
vrací kolekci List<String>
:
try { val lines = Files.readAllLines(path) lines.forEach { x: String? -> println(x) } } catch (ex: IOException) { println("Chyba při čtení souboru: " + ex.message) }
Nově vytvořený soubor newapi.txt
opět nalezneme v domovském
adresáři v podadresáři itnetwork\
a přesvědčíme se, že
opravdu obsahuje náš text.
V příští lekci , Práce s CSV soubory v Kotlin - Uložení objektů, vytvoříme formulářovou aplikaci s databází uživatelů a naučíme se ukládat instance uživatelů do 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 6x (6.9 MB)
Aplikace je včetně zdrojových kódů v jazyce Kotlin