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 o absolútnej a relatívnej ceste. Je to čisto pre to, aby sme v tom
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 na 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 od nejakého existujúceho prvku (najčastejšie k
aktuálnemu programu), napr. pictures/. Toto je určite cesta,
ktorou í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é svoje "muchy", ktoré vyústili do vytvorenia nového
API (ale o tom až v ďalšej lekcii).
Trieda reprezentuje súbor aj priečinok. Na 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ým súborom 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 môžeme 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 bude stačiť 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 hneď všetky 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 je súbor sám rodič,getParentFile(): File- vráti inštanciu triedyFilereprezentujúcu rodičov aktuálneho súboru,getPath(): String- vráti cestu k súboru (vopred nie je isté, v akom tvare ju dostaneme, 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 bolo vidno 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
Metódy SET
Metódy SET, ako už napovedá názov, 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 -> nebude možné 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.
Metódy CAN
Metódy CAN máme nasledujúce:
canExecute(): boolean- vrátitrue, ak je možné súbor spustiť, inakfalse.canRead(): boolean- vrátitrue, ak je možné zo súboru čítať, inakfalse.canWrite(): booleanvrátitrue, ak je možné do súboru zapisovať, inakfalse.
Metódy IS
Pomocou týchto metód sa môžeme pýtať na následujúce veci:
isAbsolute(): boolean- vrátitrue, ak bola inštancia vytvorená pomocou absolútnej cesty.isDirectory(): boolean- vrátitrue, ak sa jedná o zložku.isFile(): boolean- vrátitrue, ak ide o súbor.isHidden(): boolean- vrátitrue, ak je súbor skrytý.
FUNKČNÉ metódy
Z preberaných metód nám chýbajú už len 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 závislá na platforme; 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 má tieto nedostatky:
- väčšina metód vracia iba
true, alebofalsev 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 ďalšej lekcii, Práca so súbormi a priečinkami v Jave - Nové API, sa zoznámime s novými triedami na prácu so súbormi a zložkami, ktoré tieto problémy riešia.
