<< Práca so súbormi a adresármi operačného systému | Obsah | Vytvárame prvé triedy >>
Doteraz sme pracovali iba s malým počtom vstupných dát. Keď už budeme písať väčšie programy, tie už budú pravdepodobne komunikovať s okolím aj inak ako čítaním textových políčok z vyskakovacieho okna. Najčastejšie prebieha výmena dát so súbormi v operačnom systéme, databázou alebo s inými počítačmi po sieti. Niekedy programy komunikujú aj s perifériami ako tlačiareň a skener, špeciálnymi prístrojmi v nejakom podniku alebo robotmi.
Trieda File nám umožňuje identifikovať adresár alebo súbor na disku. Ale v prípade, že chceme pracovať s obsahom súborov, potrebujeme využiť niečo iné. Najjednoduchší zápis do textového súboru je s použitím triedy PrintWriter.
Práca s textovými súbormi sa vždy skladá z 3 krokov.
Na zapisovanie do súboru cez PrintWriter budeme používať metódy print(...) a println(...). Ich fungovanie je totožné s výpisom do konzoly cez System.out.print(...)
a System.out.println(...)
, akurát že výpis nie je do konzoly ale do otvoreného súboru na disku.
Uveďme si jednoduchý príklad aj s výsledným obsahom súboru.
Ak bol zápis úspešný výsledný súbor vyzerá nasledovne:
JanoJavák 0903 888 222
Určite ste zbadali bloky try a catch. V tomto prípade je ich použitie nutné, inak vám java váš kód neskompiluje. Výnimka java.io.FileNotFoundException
, teda výnimka nenájdeného súboru, je totiž považovaná za bežnú výnimku, ktorá musí byť odchytená.
Ak súbor, ktorý otvárame cez PrintWriter, neexistuje, ale existuje adresár v ktorom má byť uložený, tak sa tento súbor vytvorí. Pokiaľ súbor už existoval, premaže sa a PrintWriter doňho zapisuje od prvého znaku.
Poznámka: Aby ste sa neupísali k smrti, tak Eclipse vám vie odchytávanie výnimiek napísať za vás. Označte si oblasť, ktorú chcete mať v try bloku, kliknite prvým tlačidlom myši a vyberte možnosť Surround With > Try/catch Block.
Trieda Scanner slúži na čítanie textových súborov, vstupu z konzoly alebo z reťazca. To, čo z toho bude čítať, mu povieme pri vytváraní novej inštancie Scannera. Uveďme si používané príklady otvárania textového vstupu Scannerom:
System.in
je štandardný vstup, teda obyčajne vstup z klávesnice. Naproti tomu existuje ešte štandardný výstup System.out
, ktorý už poznáte v spojení s vypisovaním na konzolu cez metódy print(...)
a println()
. Java pozná ešte štandardný chybový výstup System.err
, do ktorého sa dá písať rovnako cez metódy print(...)
a println()
. Eclipse konzola zobrazuje výstup na štandardný chybový výstup červeným písmom.
Po vytvorení už všetky inštancie fungujú rovnako, bez ohľadu na zdroj textu, ktorý čítajú. Jediný rozdiel je v Scanneri zo súboru, ktorý by sa mal po použití zatvoriť metódou close(), aby sa zatvoril aj súbor z ktorého sa čítalo.
Filozofia fungovania Scannera je cez použitie spríbuzdnených metód:
boolean hasNextXXX()
- vráti true ak je možné zo vstupu prečítať hodnotu typu XXX, inak vráti false
XXX getXXX()
- vráti hodnotu typu XXX zo vstupu, ak to je možné
Za XXX
si môžete dosadiť primitívne typy ako napríklad int,double, boolean alebo ak nedosadíte nič a ide o String
. Scanner metódou getXXX()
číta po najbližší oddeľovač. Prednastaveným oddeľovačom je ľubovoľný znak, ktorý je takzvaným whitespace znakom, teda znakom, ktorý nie je vidieť. Typické whitespace znaky sú medzera ' '
a tabulátor '\t'
.
Špeciálnym prípadom spríbuznených metód je boolean hasNextLine() a String nextLine(), ktoré za oddeľovač považujú (neviditeľný) znak konca riadku. Výsledkom metódy String nextLine() je teda jeden riadok vstupu od aktuálnej pozície.
Keď Scanner prečíta hodnotu cez niektorú getXXX()
aktuálna pozícia sa presunie za túto hodnotu.
Prehľad niektorých metód Scannera ukazuje nasledujúca tabuľka:
metóda | činnosť |
---|---|
boolean hasNextLine() | vráti true ak je možné čítať ďalší riadok (t.j. nie sme na konci vstupu/súboru) |
String nextLine() | vráti ďalší riadok od aktuálnej pozície |
boolean hasNextInt() | vráti true ak je možné čítať ďalšie číslo typu int (t.j. dá sa skonvertovať na int) |
int nextInt() | vráti ďalšiu hodnotu typu int od aktuálnej pozície |
boolean hasNextDouble() | vráti true ak je možné čítať ďalšie číslo typu double (t.j. dá sa skonvertovať na double) |
double nextDouble() | vráti ďalšiu hodnotu typu double od aktuálnej pozície |
boolean hasNext() | vráti true ak je možné čítať ďalší reťazec |
String next() | vráti reťazec od katuálnej pozície až po najbližší oddeľovač |
useDelimiter(String) | nastaví nový oddeľovač - ak napríklad nastavíme oddeľovač na tabulátor "\t" tak medzera sa pri použití metódy next() bude brať ako bežný znak |
Načítanie 5 čísiel z klávesnice môžeme spraviť nasledovne:
Tieto čísla môžete zadať napríklad tak, že ich napíšete v jednom riadku oddelené medzerami alebo každé do nového riadku (aj nový riadok je whitespace znakom).
Načítanie 5 riadkov zo súboru môžeme spraviť nasledovne:
Poďme si ešte ukázať načítanie do dvojrozmerného poľa zo súboru. Majme nasledovný súbor, ktorý obsahuje čísla ktoré by sme chceli dostať do políčok dvojrozmerného poľa:
5 84 -8 6 12 561 5 0 0 1 -1 0
Na prvý pohľad vidíme, že pôjde o dvojrozmerné pole celých čísiel veľkosti 3x4 ktoré si nazveme matica
. Čítať zo súboru budeme po riadkoch, a každý riadok, ktorý získame metódou nextLine(), ktorý je typu String, budeme novým Scannerom čítať ako čísla oddelené whitespace oddeľovačom.
Čo však urobíme v prípade, že sa do toho súboru nepozrieme a nevieme, že koľko má matica v súbore riadkov a stĺpcov? Najprv si odhadneme maximálnu možnú veľkosť matice (v našom príklade to odhadneme na 6x6). Potom v tomto poli vyplníme iba toľko riadkov a stĺpcov, koľko ich bolo vo vstupnom súbore. Zároveň si musíme po načítaní uložiť to, koľko riadkov a stĺpcov reálne obsahuje dáta. Uložíme si to v premenných pocetRiadkov
a pocetStlpcov
. Počas napĺňania dvojrozmerného poľa si budeme spravovať premenné r
a s
, ktoré nám budú kopírovať našu aktuálnu pozíciu riadku a stĺpca.
Výsledkom tohto postupu v prípade rovnakého vstupného súboru ako v predchádzajúcom príklade budú:
pocetRiadkov
číslo 3
pocetStlpcov
číslo 4
5 | 84 | -8 | 6 | 0 | 0 |
12 | 561 | 5 | 0 | 0 | 0 |
0 | 1 | -1 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 |
Urobme si ešte výpis používanej časti tejto matice na konzolu:
Výsledkom je v našom príklade takýto výpis:
5 84 -8 6 12 561 5 0 0 1 -1 0
Zaujímavými a niekedy užitočnými sú konštruktory tried PrintWriter a Scanner s dvoma parametrami, kde prvým parametrom je otváraný súbor a druhým kódovanie znakovej sady. Keď sa použije konštruktor iba s jedným parametrom nastaví sa znaková sada projektu. Pozrieť si ju môžete kliknutím pravým tlačidlom myši na projekt a vybratie možnosti Properties. Uvidíte podobné okno:
Bežný Slovák sa stretáva najmä so znakovou sadou windows-1250 a UTF-8. Po otvorení súboru je už práca s PrintWriterom alebo Scannerom úplne rovnaká. Použitie si ukážeme na príklade s PrintWriterom.
Ak máte chuť použiť iné znakové sady kliknite si na stránku so zoznamom podporovaných kódovaní.