Aktuálně: Postihly zákazy tvou profesi? Poptávka po ajťácích prudce roste, využij slevové akce 50% výuky zdarma!
Pouze tento týden sleva až 80 % na e-learning týkající se Javy

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 systémech Windows.

Nejjednodušší cestou, jak uložit data aplikace na pevný disk, je využít textové soubory. Se soubory s příponou .txt jste 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.

Pozn.: V různých materiálech se můžete setkat s použitím různých tříd a různých způsobů k zápisu do souborů. Budu se zde snažit ukazovat způsoby, které jsou nejjednodušší a nejnovější.

Zápis textu do nového souboru

Nejprve si pojďme vytvořit nový textový soubor a něco do něj zapsat. Vytvořte si nový projekt s názvem TextoveSoubory. K zapisování do textových souborů nám Java poskytuje třídu BufferedWriter. Buffered znamená, že zapisovač využívá vyrovnávací paměť, aby urychlil zápis na disk.

Vytvořme blok try-with-resources a založme v něm novou instanci BufferedWriteru. Jak již víme z předchozích dílů, try-with-resources se nám automaticky postará o zavření souboru po dokončení zápisu/čtení. Do konstruktoru vložíme instanci FileWriteru, který BufferedWriter obaluje.

try (BufferedWriter bw = new BufferedWriter(new FileWriter("soubor.txt")))
{
}
catch (Exception e)
{
    System.err.println("Do souboru se nepovedlo zapsat.");
}

Za zmínku stojí použití System.err v bloku catch, což je chybový kanál pro výstup. V případě, že se zápis opravdu nepovede, uvidíte tento text v konzoli červenou barvou.

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Náš 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 může vypadat např. takto:

try (BufferedWriter bw = new BufferedWriter(new FileWriter("soubor.txt")))
{
    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.err.println("Do souboru se nepovedlo zapsat.");
}

Po spuštění se vytvoří soubor.txt ve složce s naším projektem. Jak se správně v Javě vypořádat s cestou k souboru a právy jsme si již ukazovali a zde to pro jednoduchost zanedbáme. Vidíme, že soubor existuje a opravdu obsahuje náš text:

Zápis textových souborů v Javě

Připsání textu do existujícího souboru

Pokud soubor neexistuje, kód výše ho vytvoří. Pokud existuje, bude přepsán. Toto chování můžeme změnit pomocí 2. parametru konstruktoru objektu FileWriter. Pokud ho nastavíme na true, provede se tzv. append (připsání). Takto do existujícího souboru připíšeme nový řádek:

try (BufferedWriter bw = new BufferedWriter(new FileWriter("soubor.txt", true)))
{
    bw.write("Připsaný řádek");
    bw.newLine();
    bw.flush();
}
catch (Exception e)
{
    System.err.println("Do souboru se nepovedlo zapsat.");
}

Pokud soubor neexistuje, bude vytvořen. Pokud existuje, bude do něj připsáno a jeho původní obsah zůstane.

Č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 readLine(), která vrací řádek textu ze souboru a zároveň se přesune na řádek následující. Budeme ji tedy volat ve while cyklu. 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 by vypadal takto:

try (BufferedReader br = new BufferedReader(new FileReader("soubor.txt")))
{
    String s;
    while ((s = br.readLine()) != null)
    {
        System.out.println(s);
    }
}
catch (Exception e)
{
    System.err.println("Chyba při čtení ze souboru.");
}

Kód celého našeho programu vypadá nyní asi takto:

// zápis do souboru
try (BufferedWriter bw = new BufferedWriter(new FileWriter("soubor.txt")))
{
    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.err.println("Do souboru se nepovedlo zapsat.");
}

// připsání textu do existujícího souboru
try (BufferedWriter bw = new BufferedWriter(new FileWriter("soubor.txt", true)))
{
    bw.write("Připsaný řádek");
    bw.newLine();
    bw.flush();
    System.out.println("Do souboru bylo připsáno");
}
catch (Exception e)
{
    System.err.println("Do souboru se nepovedlo zapsat.");
}

// výpis obsahu souboru
System.out.println("Vypisuji celý soubor:");
try (BufferedReader br = new BufferedReader(new FileReader("soubor.txt")))
{
    String s;
    while ((s = br.readLine()) != null)
    {
        System.out.println(s);
    }
}
catch (Exception e)
{
    System.err.println("Chyba při čtení ze souboru.");
}

A výsledek:

Zápis a čtení textových souborů v Javě

Opominuli jsme kontrolu práv. Do souborů také budeme chtít většinou ukládat spíše objekty, než řádky textu.

To si ukážeme dále, v lekci Uložení objektů do CSV v Javě.


 

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 811x (17.16 kB)
Aplikace je včetně zdrojových kódů v jazyce java

 

Předchozí článek
Úvod do práce se soubory v Javě
Všechny články v sekci
Soubory a síť v Javě
Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
13 hlasů
David je zakladatelem ITnetwork a programování se profesionálně věnuje 13 let. Má rád Nirvanu, sushi a svobodu podnikání.
Unicorn university David se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity (6)

 

 

Komentáře
Zobrazit starší komentáře (12)

Avatar
matrin
Člen
Avatar
matrin:26.12.2015 22:17

Potřebuji pracovat se soubory, tzn. v programu potřebuji z nějakého souboru načíst text a pak s ním i pracovat a do stejného souboru ukládat nějaké data. V jedné metodě mam, aby se zadal od uzivatele nazev souboru do promenne, ze ktere se pak cte. Z metody se vrací jit načteny text pod Stringem. Potřebuji však dále pracovat a přenášet do ostatních metod promennou, ve které je název souboru, aby se to dále ukládala data do zadaného souboru. Jste mi nekdo ochoten poradit, jestli jste z textu nějak pochopili muj problém? Díky

Takto vypadá ta metoda pro čtení ze souboru:

static String nactiText(String s) throws IOException { //funkce pro nacteni textu ze souboru
Scanner sc = new Scanner(System.in);
String soubor;
String nactenyTxt;

System.out.prin­tln(s);
soubor = sc.nextLine();

try (BufferedReader in = new BufferedReader(new FileReader(sou­bor))) {

nactenyTxt = in.readLine();
return nactenyTxt;

} catch (Exception e) {
System.err.prin­tln("Chyba při četení ze souboru.");
return "";
}
}

 
Odpovědět
26.12.2015 22:17
Avatar
pocitac770
Redaktor
Avatar
Odpovídá na matrin
pocitac770:26.12.2015 23:17

Ten text z proměnné "soubor" si můžeš překopírovat do nějaké globální statické proměnné. Pro pozdějsí užití by bylo možná ještě lepší si oddělit načítání souboru zvlášť do jiné metody a tu pak volat z mainu... Ale to je jen tip :)

Editováno 26.12.2015 23:18
 
Odpovědět
26.12.2015 23:17
Avatar
matrin
Člen
Avatar
Odpovídá na pocitac770
matrin:27.12.2015 21:52

Díky, už jsem to vyřešil. Přišel jsem ještě na další problém...pokud chci načíst text ze souboru, načte to pouze slova do prvního odstavce, tzn. dokud v textu není další řádek, když zmáčknu enter. Potřebuju aby mi to načetlo cely text, lze to nejak? Díky

 
Odpovědět
27.12.2015 21:52
Avatar
pocitac770
Redaktor
Avatar
Odpovídá na matrin
pocitac770:27.12.2015 22:26
String text;
while((text = in.readLine()) != null)
        nactenyTxt += text;

Něco takového (místo řádky "nactenyTxt = in.readLine();" )? Je to vlastně na stejném principu jako první kód pod "Čtení existujícího souboru" ;)

Editováno 27.12.2015 22:28
 
Odpovědět
27.12.2015 22:26
Avatar
koumes3
Člen
Avatar
koumes3:29.1.2017 19:27

Ahoj, chci se zeptat, zda už se někdo setkal s následujícím problémem.
Při načítání textu ze souboru, kde jsou v textu obsažené i znaky pro odřádkování a tabulátor nebo escapování uvozovek, se do textu uloží(zdvojí se) zpětné lomítka. Dočetl jsem se, že to je způsobeno tím, že se čtou znaky po jednom a tudíž narazí-li se na \ tak se automaticky escapuje a tím vznikne to dvojité \\. Vypadá to pak např. \\n \\t nebo \\". To vcelku chápu.Na co, ale nemůžu přijít ani se dočíst je, jak to zdvojení odstranit, aby pak se text zobrazil jak má. U tabulátoru a odřádkování se dá použít např. text.replace("\\t", "\t"); což ovšem u uvozovek neprojde. V kódu to hlásí chybu. Pokud by měl někdo nějaké elegantní řešení budu rád, když se se mnou podělí o zkušenost.
Díky

 
Odpovědět
29.1.2017 19:27
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
koumes3
Člen
Avatar
koumes3:29.1.2017 19:31

Ještě k předchozímu dotazu. Program jsem zkoušel v NetBeans IDE.

 
Odpovědět
29.1.2017 19:31
Avatar
Rasinsky
Člen
Avatar
Odpovídá na pocitac770
Rasinsky:26.7.2018 11:04

viem ze starsie, ale tak dalsie mozne riesenie:

Scanner fileScanner = new Scanner(UserFile);

while (fileScanner.hasNext()) {
        text =text + " " +fileScanner.next();
        }
fileScanner.close();    //nezabudat na zatvorenie scanner-u

co sa tyka escapovania asi to bude aj s NetBeans, pouzivam Eclipse, a nacita to v pohode, bez escapovania.

UserFile

pokus aaa funguje

aj prazdny riadok
"uvodzovky"
\t \n

vystup

pokus aaa funguje aj prazdny riadok "uvodzovky" \t \n

 
Odpovědět
26.7.2018 11:04
Avatar
MiroslavP
Člen
Avatar
MiroslavP:17.9.2018 21:54

Velmi užitečné a srozumitelné. děkuji.:-)

 
Odpovědět
17.9.2018 21:54
Avatar
Valerian Officinalis:27. března 19:05

Jsem lehce zmaten. Když se kouknu na internet, tak najdu několik způsobů, které mi narozdíl od těchto opravdu fungují. Rád bych to nějak podrobně popsal ale vůbec netuším kde může být problém. :/

Odpovědět
27. března 19:05
Každý je zodpovědný za svůj život. Ale ne každý je ochoten tuto zodpovědnost přijmout.
Avatar
Odpovídá na Valerian Officinalis
Valerian Officinalis:27. března 19:31

Omluvte mě prosím. To jsem klasický já, aniž bych pořádně vyzkoušel všechny možnosti a prohlédl si pořádně svůj kód, tak hned žádám o pomoc. Kéžby šel komentář vymazat :)

Odpovědět
27. března 19:31
Každý je zodpovědný za svůj život. Ale ne každý je ochoten tuto zodpovědnost přijmout.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 22. Zobrazit vše