2. diel - Úvod do práce so súbormi v Jave
V minulom dieli nášho seriálu tutoriálov o Jave, Výnimky v Jave, sme si vysvetlili výnimky, ktoré na prácu so súbormi nutne potrebujeme, pretože vďaka nim môžeme reagovať na prípadné chyby.
V dnešnom Java tutoriále si povieme niečo o súboroch ao právach na zápis na moderných operačných systémoch. Tiež si ukážeme tvorbu zástupného objektu pre súbor, s ktorým chceme pracovať.
Dáta, resp. objekty uložené v pamäti, sa samozrejme s vypnutím aplikácie stratia. Ak chceme zaistiť, aby dáta boli tzv. perzistentné (trvalé), musíme ich pri ukončení programu uložiť a pri načítaní programu opäť načítať. Na ukladanie dát existuje mnoho spôsobov, každý má svoje výhody a nevýhody.
Dáta našej aplikácie môžeme ukladať nasledujúcimi spôsobmi:
- Textové súbory s jednoduchou štruktúrou (napr.
.txt
a.csv
). - Textové súbory s vnútornou hierarchiou (napr.
.xml
alebo.json
). - Súbory binárneho typu (odtlačok pamäte do súboru).
- Databáza.
Historicky sú v Jave k práci so súbormi k dispozícii dve rôzne API:
- staršia
java.io.*
, ktorého stredobodom je triedaFile
- novší
java.nio.*
, ktorý sa točí okolo triedPath
aFiles
Obe tieto API spolu koexistujú. Hoci sa odporúča v novom kóde používať nové API, tak sa v praxi často stretneme s potrebou použiť aj to staršie, takže sa hodí poznať obe. V našom kurze sa budeme zameriavať na nové API, ale miestami si ukážeme, ako by sa daná vec robila pomocou staršieho API.
Práva na zápis na disk v moderných operačných systémoch
Všetky moderné operačné systémy majú nejaký systém prístupových práv k súborom uloženým na disku. Bežný užívateľ má obvykle právo vytvoriť súbory a zapisovať do súborov iba vo svojom domovskom adresári. Administrátor môže zapisovať kamkoľvek. Ak v našej aplikácii zakladáme súbory, musíme ich založiť tam, kde má užívateľ právo zapisovať.
V reálnej aplikácii sa používateľa najskôr spýtame,
kde chce nový súbor vytvoriť. Potom skontrolujeme, či môže do danej
lokácie zapisovať. V našich lekciách, v záujme jednoduchosti, tento krok
preskočíme. Všetky súbory budeme zakladať v podadresári
ictdemy/
v domovskom adresári užívateľa.
Domovský adresár používateľa
Domovský adresár užívateľa sa nachádza v každom systéme na inom mieste. Keďže sa snažíme tvoriť multiplatformné aplikácie, vyhneme sa špecifickým cestám k súborom v jednotlivých operačných systémoch. Java nám na to dáva prostriedky.
Domovský adresár používateľa zistíme týmto kódom:
System.getProperty("user.home");
Windows systémy
V systémoch Windows vyššie uvedený kód vráti:
C:\Users\your_name\
Všimnime si oddeľovače adresárov \
, ktorým je
spätná lomka. Windows sú tiež špecifické v označovaní
diskov písmenami (C, D, ...).
Linux systémy
V systémoch Linux vyššie uvedený kód vráti:
/home/your_name/
Operačné systémy, ktoré sa hlásia k unixovej tradícii,
používajú pre oddeľovač adresárov doprednú lomku
/
.
MacOS systém
V systéme MacOS vyššie uvedený kód vráti:
/Users/your_name
Systém MacOS používa pre oddeľovač adresárov aj
doprednú lomku /
.
Vytvorenie Path
z
nového API java.nio.*
Základom úspešnej práce so súbormi v Jave je mať správne vytvorenú
inštanciu triedy Path
(pri použití novšieho
API), alebo File
(pri použití staršieho API). Táto inštancia
triedy reprezentuje cestu k súboru, s ktorým chceme
pracovať. Čítanie súboru, alebo zápis do súboru potom prebieha za pomoci
tejto inštancie.
Poďme sa teda najprv pozrieť na to, ako správne vytvoriť inštanciu
triedy Path
. Na vytvorenie inštancie triedy Path
slúži statická metóda of()
volaná na triede
Path
:
Path path = Path.of(file_path);
Príklad
Napríklad cestu k súboru file.txt
, v podadresári
ictdemy
, v našom domovskom adresári definujeme takto:
Path path = Path.of(System.getProperty("user.home"), "ictdemy", "file.txt");
V kóde neriešime špecifické cesty k súboru pre jednotlivé
operačné systémy. System.getProperty()
dosadí správnu cestu
pre platformu, na ktorej je aplikácia spustená.
Inštancia triedy Path
je ukazovateľ na miesto na
disku, kde môže, ale nemusí daný súbor byť. Taktiež nemusí
existovať všetky adresáre v ceste k súboru. Napríklad v našom príklade je
možné, že ešte nemáme v našom domovskom adresári adresár
ictdemy/
.
Kontrola adresárov
Poďme sa teda najprv uistiť, že všetky potrebné adresáre naozaj
existujú a prípadne ich vytvoriť. Na tento účel slúži statická
metóda createDirectories()
z triedy
Files
:
Path path = Path.of(System.getProperty("user.home"), "ictdemy", "file.txt"); Files.createDirectories(path.getParent());
Metóda getParent()
vracia adresár, v ktorom sa nachádza
file.txt
. V našom príklade je to adresár ictdemy/
.
Metóda createDirectories()
vytvorí celú potrebnú hierarchiu
adresárov vrátane ictdemy/
.
Pokiaľ by niektorý adresár už existoval, metóda
createDirectories()
vytvorenie adresára preskočí bez vyvolania
výnimky. Preto je vhodné ju použiť pri každom definovaní cesty k
súboru.
Vytvorenie File
zo staršieho API java.io.*
Pri použití staršieho API pracujeme s triedou File
.
Vytvorenie samotnej inštancie je tu veľmi podobné:
File path = new File("file_path");
Na rozdiel od triedy Path
, trieda File
očakáva cestu k súboru ako jeden String
.
Príklad
Rovnako ako v prípade Path
, aj tu môžeme využiť
System.getProperty()
na získanie cesty k domovskému
adresáru. Našu cestu k súboru file.txt
, v podadresári
ictdemy/
, v našom domovskom adresári tu definujeme takto:
File path = new File(System.getProperty("user.home") + File.separator + "ictdemy" + File.separator + "file.txt");
Pomocou File.separator
vytvoríme platnú cestu pre
akúkoľvek platformu.
Kontrola adresárov
Rovnako ako v prípade Path
aj teraz potrebujeme skontrolovať,
či existujú všetky definované adresáre. Na to využijeme
metódu mkdirs()
, ktorú tentoraz zavoláme na inštanciu triedy
File
:
File path = new File(System.getProperty("user.home") + File.separator + "ictdemy" + File.separator + "file.txt"); path.getParentFile().mkdirs();
Pred samotným zavolaním mkdirs()
zavoláme
metódu getParentFile()
. Metóda getParentFile()
vráti adresár, v ktorom sa bude nachádzať file.txt
.
Prevediteľnosť Path
<->
File
Triedy Path
a File
ponúkajú jednoduchú konverziu
medzi sebou.
Konverzia Path
na
File
Pre prevedenie cesty k súboru z inštancie triedy Path
na
inštanciu triedy File
, zavoláme metódu toFile()
na
inštanciu triedy Path
:
Path path = Path.of(...); File file = path.toFile();
Konverzia File
na
Path
Pre prevedenie cesty k súboru z inštancie triedy File
na
inštanciu triedy Path
, zavoláme metódu toPath()
na
inštanciu triedy File
:
File file = new File(...);
Path path = file.toPath();
Teraz už teda vieme ako správne vytvoriť inštancie tried
Path
a File
na použitie na akomkoľvek operačnom
systéme.
Nič nám už nebráni, aby sme si nabudúce, Práca s textovými súbormi v Jave, ukázali prácu s prvým formátom súborov, budú to textové súbory.