13. diel - Práca so súbormi a priečinkami v Kotlin - Trieda File
V predchádzajúcom cvičení, Riešené úlohy k 6.-10. lekciu práce so súbormi v Kotlin, sme si precvičili získané skúsenosti z predchádzajúcich lekcií.
Dnes si popíšeme triedy v Kotline, 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 nášho tutoriálu 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 poriadok, aby sme
mali jasno.
Absolútna cesta
Absolútna cesta začína koreňovým prvkom súborového systému. V
prípade Windows to bude 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 závislá na platforme. 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. obrazky/
. Toto je rozhodne spôsob,
kadiaľ ísť v prípade práce so súbormi v programe.
Trieda File
Triedu File
poskytuje Java už od prvej verzie. Môžeme ju teda
bez problémov využiť aj na tvorbu našich Kotlín aplikácií. Postupom času
sa však ukázalo, že má nejaké "muchy", ktoré vyústili do vytvorenia
nového API. To si predstavíme v ďalších lekciách.
Trieda File
reprezentuje ako súbor, tak aj
zložku. Na prácu so súborom alebo priečinkom je potrebné
vytvoriť novú inštanciu. To sa dá urobiť veľmi jednoducho:
val file = File("soubor.txt")
Konštruktor má celkom 4 preťaženia:
File(String pathname) File(String parent, String child) File(File parent, String child) 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ý .kt
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 alebo zložka, ktorá
sa nachádza v nadradenej zložke, napríklad C://soubor.txt
.
Tretie preťaženie 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.
URI si nebudeme pliesť s URL. 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.
Kompletný syntax pre URI vyzerá nasledovne:
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/soubor.txt
S týmto prístupom sa najčastejšie stretneme pri použití
rôznych obrázkov, zvukov a ďalších súborov. 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,
- funkčné.
Máme k dispozícii nasledujúce GET 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, ale 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 oddiele, 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()
.
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 |---cz | |---itnetwork | |---souboryslozky | |---App.java |---soubory | |---soubor.txt
Inštanciu triedy File
vytvoríme takto:
val file = File("../../../soubory/soubor.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:
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 metódy
SET metódy, ako 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 uvádzať nemusíme, potom má hodnotutrue
a 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 a 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 máme nasledujúce:
canExecute(): boolean
- vrátitrue
, ak je možné súbor spustiť,canRead(): boolean
- vrátitrue
, pokiaľ je možné zo súboru čítať,canWrite(): boolean
vrátitrue
, pokiaľ je možné do súboru zapisovať.
Pomocou IS metód sa môžeme pýtať na tieto 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ý.
Z preberaných metód nám už len chýba tzv. funkčné metódy, teda také metódy, ktoré niečo vykonáva 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 a vrátitrue
, ak sa súbor podarilo vytvoriť,delete(): boolean
- zmaže súbor a vrátitrue
, pokiaľ sa ho zmazať podarilo,deleteOnExit(): void
- zmaže súbor až po ukončení programu,exists(): boolean
- vrátitrue
, ak súbor existuje,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 a vrátitrue
, ak sa zložka vytvorila,mkdirs(): boolean
- pokúsi sa vytvoriť všetky zložky v ceste, opäť vrátitrue
, pokiaľ sa všetky zložky vytvorili,renameTo(File dest): boolean
- premenuje súbor na nové meno, čo je možné chápať ako "presun" súboru z jedného miesta na druhé, metóda je platforme závislá a nie je možné použiť na presun súboru medzi dvoma súborovými systémami,toPath(): Path
- vytvorí novú inštanciu rozhraniaPath
.
File
API
File
API trpí nasledujúcimi nedostatkami:
- Veľká väčšina metód vracia iba
false
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 Kotlin - Nové API , sa zoznámime s novými triedami pre prácu so
súbormi a zložkami, ktoré problémy riešia nedostatky staršej triedy
File
.