17. diel - Práca so súbormi a priečinkami v Jave
V predchádzajúcom kvíze, Kvíz - Pokročilá práca s výnimkami v Jave, sme si overili nadobudnuté skúsenosti z predchádzajúcich lekcií.
Dnes si popíšeme triedy v Jave, ktoré nie sú nijak závislé od typu
súboru a ich použitie je teda všeobecné. Umožňujú pracovať so súbormi a
priečinkami na úrovni operačného systému, čo určite budeme v našich
aplikáciách potrebovať. V tejto lekcii si predstavíme triedu
File
, jej metódy a použitie.
Absolútna vs. relatívna cesta
Než sa pustíme do popisu triedy File
, v krátkosti si niečo
povieme k absolútnej a relatívnej ceste. Je to čisto pre poriadok, aby sme
mali jasno.
Absolútna cesta
Je taká cesta, ktorá začína koreňovým prvkom súborového systému. V
prípade Windows to bude niečo ako: C:\\
alebo D:\\
,
pre Linux to bude veľmi jednoducho /
. Absolútna cesta nepotrebuje
žiadne ďalšie informácie na určenie umiestnenia súboru. Všetko je na
jednom mieste. Problém ale je, že cesta je platforme závislá. Ako už bolo
naznačené, pre Windows a Linux sa líšia. Preto odporúčam absolútne cesty
v ideálnom prípade nepoužívať. Prípadne iba pre súbory s nastavením
programu.
Relatívna cesta
Relatívna cesta nezačína v koreni súborového systému. Namiesto toho sa
počíta v závislosti k nejakému existujúcemu prvku (najčastejšie k
aktuálnemu programu), napr. pictures/
. Toto je rozhodne cesta
kadiaľ ísť v prípade práce so súbormi v programe.
Trieda File
Trieda File
je v Jave už od prvej verzie. Postupom času sa
ukázalo, že má nejaké "muchy", ktoré vyústili do vytvorenia nového API
(ale o tom až v budúcej lekcii).
Trieda reprezentuje ako súbor, tak aj priečinok. Pre prácu so súborom/priečinkom je potrebné vytvoriť novú inštanciu. To sa dá urobiť veľmi jednoducho:
File file = new File("file.txt");
Konštruktor má celkom 4 preťaženia:
public File(String pathname); public File(String parent, String child); public File(File parent, String child) public File(URI uri)
V prvom prípade je možné dosadiť ako absolútnu, tak relatívnu cestu. Ak použijete relatívnu cestu, výsledok sa bude vždy počítať z použitého súboru.
Použitý súbor sa myslí výsledný JAR
súbor, nie *.class
.
Druhé preťaženie prijíma dva reťazce. Prvý reťazec predstavuje cestu k rodičovi a môže byť relatívny aj absolútny. Druhý parameter je cesta relatívna k rodičovi v prvom parametri.
Rodič je akákoľvek nadradená zložka, napríklad
C://
. Potomok je súbor/priečinok, ktorý sa nachádza v
nadradenej zložke, napríklad: C://file.txt
.
Tretie preťaženie je rovnako ako prvé, iba sa líši v prvom parametri,
ktorým je teraz iná inštancia triedy File
.
Posledné preťaženie prijíma tzv. URI. Je to skratka pre Uniform Resource Identifier. (Nepliesť s URL). Kompletný syntax pre URI je vidieť nižšie:
URI je štandard pre identifikáciu dokumentov, využívajúci schému popísanú nižšie. URL je "podmnožina" URI a obsahuje informácie, ako spracovať zdroje z nejakého umiestnenia.
scheme:[//[user:password@]host[:port]][/]path[?query][#fragment]
Toto je všeobecná schéma. Nám postačí iba základné, kde za časť
scheme
dosadíme file
a potom až cestu:
file:/tmp/file.txt
S týmto prístupom sa najčastejšie stretneme pri použití
rôznych obrázkov, zvukov a ďalších súborov, ktoré zabalíme do JARu. K
týmto súborom obvykle pristupujeme pomocou metódy
getClass().getResource(String name)
. Táto metóda vracia práve
URI, ktoré odovzdáme konštruktoru triedy File
.
Najčastejšie ale budeme pracovať s prvým preťažením konštruktora.
Metódy triedy File
Metódy si roztriedime do niekoľkých kategórií:
get*()
,set*()
,can*()
,is*()
- a funkčné.
GET metódy
V prvej katégorii máme k dispozícii nasledujúce metódy, ktoré si všetky hneď prakticky vyskúšame:
getAbsolutePath(): String
- vráti absolútnu cestu k súboru,getCanonicalPath(): String
- vráti canonizovanú cestu k súboru,getFreeSpace(): long
- vráti počet voľných bytov v oddieli, v ktorom sa súbor nachádza,getName(): String
- vráti názov súboru,getParent(): String
- vráti absolútnu cestu k rodičovi, alebonull
, ak súbor je sám rodič,getParentFile(): File
- vráti inštanciu triedyFile
reprezentujúce rodičov aktuálneho súboru,getPath(): String
- vráti cestu k súboru (vopred nie je isté, v akom tvare ju dostanete, preto je lepšie používaťgetCanonicalPath()
,getTotalSpace(): long
- vráti celkový počet bytov v oddieli, v ktorom sa súbor nachádza,getUsableSpace(): long
- vráti počet použiteľných bytov pre aktuálny virtuálny stroj; výsledok je presnejší, než z metódygetFreeSpace()
.
Pre istotu si napíšeme aj príklady použitia. Vytvoríme jednu inštanciu
triedy File
a zavoláme nad ňou všetky GET metódy.
Na demonštráciu som schválne vytvoril nešikovnú zložkovú štruktúru, aby boli vidieť rozdiely medzi jednotlivými metódami. Zložky sú vytvorené nasledovne:
src |---com | |---ictdemy | |---filesFolders | |---App.java |---files | |---file.txt
Inštanciu triedy File
vytvoríme takto:
File file = new File("../../../files/file.txt");
Schválne sme použili niekoľkokrát sekvenciu
../
, ktorá nás vráti o zložku späť vzhľadom k aktuálnej
zložke, aby bol výsledok zaujímavejší.
Výstup jednotlivých metód:
Konzolová aplikácia
getAbsolutePath(): /tmp/ict/filesFolders/../../../files/file.txt
getCanonicalPath(): /files/file.txt
getFreeSpace(): 0
getName(): file.txt
getParent(): ../../../files
getParentFile(): ../../../files
getPath(): ../../../files/file.txt
getTotalSpace(): 0
getUsableSpace(): 0
SET metódy
SET metódy, ako už názov napovedá, súborom nastavujú nejaké vlastnosti. Sú to:
setExecutable(boolean executable, boolean ownerOnly): boolean
- nastaví, či je súbor spustiteľný; druhý parameter je nepovinný (existuje preťaženie, kedy sa tento parameter automaticky nastaví natrue
); ak je druhý parametertrue
, tak sa spustiteľnosť nastaví iba aktuálnemu užívateľovi.setLastModified(long time): boolean
- nastaví dátum poslednej zmeny súboru.setReadable(boolean readable, boolean ownerOnly): boolean
- nastaví, či je súbor možné čítať; pre druhý parameter platí to isté ako pri prvej metóde.setReadOnly(): boolean
- jednosmerná metóda, pomocou ktorej sa nastaví súbor iba na čítanie -> nepôjde do neho zapisovať.setWritable(boolean writable, boolean ownerOnly): boolean
- nastaví, či je možné do súboru zapisovať; pre druhý parameter platí to isté ako pri prvej metóde.
CAN metódy
CAN metódy máme nasledujúce:
canExecute(): boolean
- vrátitrue
, ak je možné súbor spustiť, inakfalse
.canRead(): boolean
- vrátitrue
, pokiaľ je možné zo súboru čítať, inakfalse
.canWrite(): boolean
vrátitrue
, pokiaľ je možné do súboru zapisovať, inakfalse
.
IS metódy
Pomocou týchto metód sa môžeme pýtať na následujúce veci:
isAbsolute(): boolean
- vrátitrue
, ak bola inštancia vytvorená za pomoci absolútnej cesty.isDirectory(): boolean
- vrátitrue
, pokiaľ sa jedná o zložku.isFile(): boolean
- vrátitrue
, pokiaľ ide o súbor.isHidden(): boolean
- vrátitrue
, ak je súbor skrytý.
FUNKČNÉ metódy
Z preberaných metód nám už len chýba tzv. "funkčné" metódy, teda také metódy, ktoré niečo vykonávajú so samotným súborom a ktoré budeme využívať najčastejšie:
toURI(): URI
- vytvorí URI z použitej inštancie súboru.createNewFile(): boolean
- vytvorí nový súbor pokiaľ neexistuje; vrátitrue
, ak sa súbor podarilo vytvoriť, inakfalse
.delete(): boolean
- zmaže súbor; vrátitrue
, ak sa súbor podarilo zmazať, inakfalse
.deleteOnExit(): void
- zmaže súbor až po ukončení programu.exists(): boolean
- vrátitrue
, ak súbor existuje, inakfalse
.length(): long
- vráti veľkosť súboru v bytoch.list(): String[]
- vráti pole absolútnych ciest súborov v priečinku.listFiles(): File[]
- vráti pole inštancií súboru v priečinku.mkdir(): boolean
- pokúsi sa vytvoriť zložku; vrátitrue
, ak sa zložka vytvorila, inakfalse
.mkdirs(): boolean
- pokúsi sa vytvoriť všetky zložky v ceste; vrátitrue
, ak sa všetky zložky vytvorili, inakfalse
.renameTo(File dest): boolean
- premenuje súbor na nové meno; možno chápať ako "presun" súboru z jedného miesta na druhé; metóda je platforme závislá; nie je možné použiť na presun súboru medzi dvoma súborovými systémami.toPath(): Path
- vytvorí novú inštanciu rozhraniaPath
, o ktorom si povieme v budúcej lekcii.
Problémy File API
File API trpí nasledujúcimi nedostatkami:
- valná väčšina metód vracia iba
true
, alebofalse
v prípade, že sa niečo nepodarí; problém je, že nepoznáme príčinu neúspechu, - premenovanie súboru nefunguje na všetkých platformách rovnako,
- API nepodporuje symbolické linky,
- v API chýba podpora metadát (oprávnenie, vlastník súboru...).
V budúcej lekcii, Práca so súbormi a priečinkami v Jave - Nové API, sa zoznámime s novými triedami pre prácu so súbormi a zložkami, ktoré tieto problémy riešia.