Lekce 3 - Práce s textovými soubory v Javě
V minulém dílu seriálu tutoriálů pro Javu, Úvod do práce se soubory v Javě, 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 Java tutoriálu si vysvětlíme práci s textovými soubory pomocí staršího API java.io a novějšího API 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ší Java.
API java.io
Pojďme se nejprve podívat na starší způsob práce se soubory pomocí API java.io.
Zápis do nového textového souboru
Vytvoříme si nový projekt s názvem TextoveSoubory a v
něm třídu Main
s obvyklou metodou main()
. 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 této lekci.
Soubor pojmenujeme třeba oldapi.txt
.
File file = new File(System.getProperty("user.home") + File.separator + "itnetwork" + File.separator + "oldapi.txt"); file.getParentFile().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 bw = new BufferedWriter(new FileWriter(file))) { } catch (Exception e) { System.out.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:
File file = new File(System.getProperty("user.home") + File.separator + "itnetwork" + File.separator + "oldapi.txt"); file.getParentFile().mkdirs(); try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) { 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(); } catch (Exception e) { System.out.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 bw = new BufferedWriter(new FileWriter(file, true))) { bw.write("Připsaný řádek"); bw.newLine(); bw.flush(); } catch (Exception e) { System.out.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 br = new BufferedReader(new FileReader(file))) { String s; while ((s = br.readLine()) != null) { System.out.println(s); } } catch (Exception e) { System.out.println("Chyba při čtení ze souboru."); }
Kód celého našeho programu vypadá takto:
// zápis do souboru File file = new File(System.getProperty("user.home") + File.separator + "itnetwork" + File.separator + "oldapi.txt"); file.getParentFile().mkdirs(); try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) { 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(); System.out.println("Do souboru bylo zapsáno"); } catch (Exception e) { System.out.println("Do souboru se nepovedlo zapsat."); } // připsání textu do existujícího souboru try (BufferedWriter bw = new BufferedWriter(new FileWriter(file, true))) { bw.write("Připsaný řádek"); bw.newLine(); bw.flush(); System.out.println("Do souboru bylo připsáno"); } catch (Exception e) { System.out.println("Do souboru se nepovedlo zapsat."); } // výpis obsahu souboru System.out.println("Vypisuji celý soubor:"); try (BufferedReader br = new BufferedReader(new FileReader(file))) { String s; while ((s = br.readLine()) != null) { System.out.println(s); } } catch (Exception e) { System.out.println("Chyba při čtení ze souboru."); }
A výsledek:
API java.nio
Teď se podíváme na novější způsob práce se soubory pomocí API java.nio.
Zápis do nového textového souboru
Nejprve si vytvoříme instanci třídy Path
. Soubor pojmenujeme
třeba newapi.txt
:
Path 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ž existujeCREATE_NEW
- vytvoří nový soubor, vyhodí chybu, pokud soubor už existujeTRUNCATE_EXISTING
- při otevření vymaže obsah souboruAPPEND
- 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.getParent()); Files.writeString(path, "První řádek" + System.lineSeparator(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); 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.getMessage()); }
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 posledním řádku" + System.lineSeparator(), StandardOpenOption.APPEND); } catch (IOException ex) { System.out.println("Chyba při zápisu do souboru: " + ex.getMessage()); }
Č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 { List<String> lines = Files.readAllLines(path); lines.forEach(System.out::println); } catch (IOException ex) { System.out.println("Chyba při čtení souboru: " + ex.getMessage()); }
V následujícím kvízu, Kvíz - Základy práce se soubory a výjimky v Javě, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.
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 867x (3.35 kB)
Aplikace je včetně zdrojových kódů v jazyce Java