Lekce 17 - Práce se soubory a složkami v Javě
Dnes si popíšeme třídy v Javě, které nejsou nijak závislé na typu
souboru a jejich použití je tedy obecné. Umožňují pracovat se soubory a
složkami na úrovni operačního systému, což jistě budeme v našich
aplikacích potřebovat. V této lekci si představíme třídu
File
, její metody a použití.
Absolutní vs. relativní cesta
Než se pustíme do popisu třídy File
, v krátkosti si něco
řekneme k absolutní a relativní cestě. Je to čistě pro pořádek, abychom
měli jasno.
Absolutní cesta
Je taková cesta, která začíná kořenovým prvkem souborového systému.
V případě Windows to bude něco jako: C:\\
nebo
D:\\
, pro Linux to bude velice jednoduše /
.
Absolutní cesta nepotřebuje žádné další informace k určení umístění
souboru. Vše je na jednom místě. Problém ale je, že cesta je platformě
závislá. Jak již bylo naznačeno, pro Windows a Linux se liší. Proto
doporučuji absolutní cesty v ideálním případě nepoužívat. Případně
pouze pro soubory s nastavením programu.
Relativní cesta
Relativní cesta nezačíná v kořeni souborového systému. Na místo toho
se počítá v závislosti k nějakému existujícímu prvku (nejčastěji k
aktuálnímu programu), např. obrazky/
. Toto je rozhodně cesta
kudy jít v případě práce se soubory v programu.
Třída File
Třída File
je v Javě již od první verze. Postupem času se
ukázalo, že má nějaké "mouchy", které vyústily ve vytvoření nového API
(ale o tom až v příští lekci).
Třída reprezentuje jak soubor, tak i složku. Pro práci se souborem/složkou je potřeba vytvořit novou instanci. To lze provést velmi jednoduše:
File file = new File("soubor.txt");
Konstruktor má celkem 4 přetížení:
public File(String pathname); public File(String parent, String child); public File(File parent, String child) public File(URI uri)
V prvním případě lze dosadit jak absolutní, tak relativní cestu. Pokud použijete relativní cestu, výsledek se bude vždy počítat z použitého souboru.
Použitý soubor se myslí výsledný JAR soubor, ne *.class.
Druhé přetížení přijímá dva řetězce. První řetězec představuje cestu k rodiči a může být jak relativní, tak absolutní. Druhý parametr je cesta relativní k rodiči v prvním parametru.
Rodič je jakákoliv nadřazená složka, například "C://". Potomek je soubor/složka, která se nachází v nadřazené složce, například: "C://soubor.txt"
Třetí přetížení je stejně jako první, pouze se liší v prvním
parametru, kterým je nyní jiná instance třídy File
.
Poslední přetížení přijímá tzv. URI. Je to zkratka pro Uniform Resource Identifier. (Neplést s URL). Kompletní syntax pro URI je vidět níže:
URI je standard pro identifikaci dokumentů, využívající schéma popsané níže. URL je "podmnožina" URI a obsahuje informace, jak zpracovat zdroje z nějakého umístění.
scheme:[//[user:password@]host[:port]][/]path[?query][#fragment]
Toto je obecné schéma. Nám postačí pouze základní, kde za část "scheme" dosadíme 'file' a pak až cestu.
file:/tmp/soubor.txt
S tímto přístupem se nejčastěji setkáme při použití
různých obrázků, zvuků a dalších souborů, které zabalíme do JARu. K
těmto souborům obvykle přistupujeme pomocí metody
getClass().getResource(String name)
. Tato metoda vrací právě
URI, které předáme konstruktoru třídy File
.
Nejčastěji ale budeme pracovat s prvním přetížením konstruktoru.
Metody třídy File
Metody si roztřídíme do několika kategorií:
- get
- set
- can
- is
- funkční
GET metody
Máme k dispozici následující get metody, které si všechny hned prakticky vyzkoušíme:
getAbsolutePath(): String
- vrátí absolutní cestu k souborugetCanonicalPath(): String
- vrátí canonizovanou cestu k souborugetFreeSpace(): long
- vrátí počet volných bytů v oddílu, ve kterém se soubor nacházígetName(): String
- vrátí název souborugetParent(): String
- vrátí absolutní cestu k rodiči, nebonull
, pokud soubor je sám rodičgetParentFile(): File
- vrátí instanci třídyFile
reprezentující rodiče aktuálního souborugetPath(): String
- vrátí cestu k souboru (předem není jisté, v jakém tvaru ji dostanete, proto je lepší používatgetCanonicalPath()
getTotalSpace(): long
- vrátí celkový počet bytů v oddílu, ve kterém se soubor nacházígetUsableSpace(): long
- vrátí počet použitelných bytů pro aktuální virtuální stroj; výsledek je přesnější, než z metodygetFreeSpace()
Pro jistotu si napíšeme i příklady použití. Vytvoříme jednu instanci
třídy File
a zavoláme nad ní veškeré GET metody.
Pro demonstraci jsem schválně vytvořil nešikovnou složkovou strukturu, aby byly vidět rozdíly mezi jednotlivými metodami. Složky jsou vytvořeny následovně:
src |---cz | |---itnetwork | |---souboryslozky | |---App.java |---soubory | |---soubor.txt
Instanci třídy File
vytvoříme takto:
File file = new File("../../../soubory/soubor.txt");
Schválně jsme použili několikrát sekvenci ../
,
která nás vrátí o složku zpět vzhledem k aktuální složce, aby byl
výsledek zajímavější.
Výstup jednotlivých metod:
Konzolová aplikace
getAbsolutePath(): /tmp/itn/soubory-slozky/../../../soubory/soubor.txt
getCanonicalPath(): /soubory/soubor.txt
getFreeSpace(): 0
getName(): soubor.txt
getParent(): ../../../soubory
getParentFile(): ../../../soubory
getPath(): ../../../soubory/soubor.txt
getTotalSpace(): 0
getUsableSpace(): 0
SET metody
Set metody, jak název již napovídá, souborům nastavují nějaké vlastnosti. Jsou to:
setExecutable(boolean executable, boolean ownerOnly): boolean
- nastaví, zda-li je soubor spustitelný; druhý parametr je nepovinný (existuje přetížení, kdy se tento parametr automaticky nastaví natrue
); pokud je druhý parametrtrue
, tak se spustitelnost nastaví pouze aktuálnímu uživatelisetLastModified(long time): boolean
- nastaví datum poslední změny souborusetReadable(boolean readable, boolean ownerOnly): boolean
- nastaví, zda-li je soubor možné číst; pro druhý parametr platí to samé jako u první metodysetReadOnly(): boolean
- jednosměrná metoda, pomocí které se nastaví soubor pouze pro čtení -> nepůjde do něj zapisovatsetWritable(boolean writable, boolean ownerOnly): boolean
- nastaví, zda-li je možné do souboru zapisovat; pro druhý parametr platí to samé jako u první metody
CAN metody
Can metody máme následující:
canExecute(): boolean
- vrátítrue
, pokud lze soubor spustit, jinakfalse
canRead(): boolean
- vrátítrue
, pokud lze ze souboru číst, jinakfalse
canWrite(): boolean
vrátítrue
, pokud lze do souboru zapisovat, jinakfalse
IS metody
Pomocí "IS" metod se můžeme ptát na tyto věci:
isAbsolute(): boolean
- vrátítrue
, pokud byla instance vytvořena za pomoci absolutní cestyisDirectory(): boolean
- vrátítrue
, pokud se jedná o složkuisFile(): boolean
- vrátítrue
, pokud se jedná o souborisHidden(): boolean
- vrátítrue
, pokud je soubor skrytý
FUNKČNÍ metody
Z probíraných metod nám už jenom chybí tvz. "funkční" metody, tedy takové metody, které něco provádí se samotným souborem a které budeme využívat nejčastěji.
toURI(): URI
- vytvoří URI z použité instance souborucreateNewFile(): boolean
- vytvoří nový soubor pokud neexistuje; vrátítrue
, pokud se soubor podařilo vytvořit, jinakfalse
delete(): boolean
- smaže soubor; vrátítrue
, pokud se soubor podařilo smazat, jinakfalse
deleteOnExit(): void
- smaže soubor až po ukončení programuexists(): boolean
- vrátítrue
, pokud soubor existuje, jinakfalse
length(): long
- vrátí velikost souboru v bytechlist(): String[]
- vrátí pole absolutních cest souborů ve složcelistFiles(): File[]
- vrátí pole instancí souboru ve složcemkdir(): boolean
- pokusí se vytvořit složku; vrátítrue
, pokud se složka vytvořila, jinakfalse
mkdirs(): boolean
- pokusí se vytvořit všechny složky v cestě; vrátítrue
, pokud se všechny složky vytvořily, jinakfalse
renameTo(File dest): boolean
- přejmenuje soubor na nové jméno; lze chápat jako "přesun" souboru z jednoho místa na druhé; metoda je platformě závislá; nelze použít pro přesun souboru mezi dvěma souborovými systémytoPath(): Path
- vytvoří novou instanci rozhraníPath
, o kterém si povíme v příští lekci
Problémy File API
File
API trpí následujícími nedostatky:
- valná většina metod vrací pouze
true
, nebofalse
v případě, že se něco nepovede; problém je, že neznáme příčinu neúspěchu - přejmenování souboru nefunguje na všech platformách stejně
- API nepodporuje symbolické linky
- v API chybí podpora metadat (oprávnění, vlastník souboru...)
V příští lekci, Práce se soubory a složkami v Javě - Nové API, se seznámíme s novými třídami pro práci se soubory a složkami, které tyto problémy řeší.