Lekce 16 - Práce s vlastními soubory v Kotlin - ZIP archiv
V minulé lekci, Práce se soubory a složkami v Kotlin - Nové API, jsme si ukázali práci se soubory a složkami v Kotlin pomocí tříd zavedených od Javy 7.
Nyní již umíme pracovat se spoustou druhů souborů. Víme, jak je ukládat a otevírat, přehrávat, odchytávat chyby. V dnešním dílu našeho Kotlin tutoriálu si ukážeme další možnost práce se soubory, a to s použitím ZIP archivu.
ZIP archivy
Představme si reálnou aplikaci k evidenci zaměstnanců. Zaměstnanec v ní má textové údaje (jméno, příjmení a email), datum (datum narození), číslo (telefonní číslo) a obrázek (fotografii). Už jen kvůli obrázku může být na první pohled problém všechna tato data uložit, a to ideálně do jednoho jediného souboru. Teoreticky bychom mohli zvolit nějaký binární formát dat (kvůli obrázku) a vložit do něj i textové údaje. Prakticky jsou ale binární soubory poměrně nešikovné a špatně se s nimi reaguje na změny formátu.
Podobné aplikace často využívají k ukládání dat archivy. Vezměme si
takový MS-Word a jeho dokumenty s příponou souborů .docx
. Když
změníme příponu libovolného .docx
souboru na
.zip
, zjistíme, že dokument je ve skutečnosti archiv ZIP, pouze
s jinou příponou. Zkuste si to.
Windows skrývají ve výchozím nastavení přípony souborů
známých typů, takže místo Dokument.docx
vidíme jen
Dokument
. Nastavení změníme v záložce Zobrazení, v
okně Zobrazit či skrýt zaškrtnutím políčka Přípony názvů
souborů.
Jako archiv v sobě může soubor obsahovat jednoduše několik souborů a
navenek se tváří pro nic netušícího uživatele jako jeden. Přesně
archivu ZIP využijeme i k uložení našeho zaměstnance. A místo
.zip
nastavíme souboru úplně jinou příponu, nabízí se
.zamestnanec
nebo zkráceně .zam
.
Přípona souboru slouží jen k tomu, aby operační systém Windows zjistil, v jaké aplikaci má soubor otevřít, když na něj uživatel poklepe. Většinou platí, že má každý soubor na konci svého názvu tečku a třípísmennou příponu. Ve skutečnosti nemusí mít soubor příponu vůbec žádnou, může jich mít více, mohou být delší než tři znaky a dokonce nemusí vůbec odpovídat tomu, co je v souboru uložené.
My budeme soubor .zip
maskovat jako soubor .zam
.
Zip neponecháme z toho důvodu, aby to uživatele nezmátlo a nezačal soubory
rozbalovat a měnit.
Formát souborů .zam
Struktura zazipované složky bude následující:
data.zam
zamestnanci.xml
obrazky/
jmenoprijmeni_1.png
jmenoprijmeni_2.png
Soubor zamestnanci.xml
bude vypadat například takto:
<zamestnanci> <zamestnanec> <jmeno>Tomáš</jmeno> <prijmeni>Šeldosklepa</prijmeni> <email>[email protected]</email> <telefon>123456789</telefon> <narozeni>1.1.1970</narozeni> </zamestnanec> </zamestnanci>
Element <zamestnanci>
obalující
zaměstnance je zde proto, že aplikace může někdy v budoucnu zpracovávat
více zaměstnanců. Nad takovými "drobnostmi" je potřeba při návrhu
přemýšlet.
Tvorba aplikace
Vytvořme si nový projekt, formulářovou aplikaci. Pod článkem je k dispozici archiv s projektem. V projektu již jsou vygenerované všechny potřebné formulářové prvky a navěšeny obsluhy tlačítek:

Třída Zamestnanec
Začneme tím, co by mělo být jasné, tedy vlastnostmi. Náš zaměstnanec bude mít:
- jméno,
- příjmení,
- email,
- telefon,
- datum narození
- a bude mít i fotografii.
Ve třídě si ještě přepíšeme metodu toString()
, celý
kód pak vypadá takto:
class Zamestnanec @JvmOverloads constructor( var jmeno: String = "", var prijmeni: String = "", var email: String = "", var telefon: String = "", var narozeniny: LocalDate = LocalDate.now() ) { var obrazek: BufferedImage? = null override fun toString(): String { return "Zamestnanec{jmeno=$jmeno, prijmeni=$prijmeni}" } }
Konstruktor jsme označili anotací @JvmOverloads
, protože jej
použijeme pro dvě přetížení. První přetížení vytvoří prázdného
zaměstnance. Pomocí druhého vytvoříme instanci zaměstnance se všemi
údaji, kromě obrázku. Anotací @JvmOverloads
pak zajistíme
interoperabilitu s Javou, kde bychom museli deklarovat konstruktory dva.
Úprava kontroleru
Do projektu si nyní přidáme kontroler DatabazeKontroler
a
deklarujeme v něm kolekci zaměstnanců a jednotlivé položky z
formuláře:
class DatabazeKontroler { private val zamestnanci = mutableListOf<Zamestnanec>() @FXML private lateinit var obrazekView: ImageView @FXML private lateinit var jmenoTextField: TextField @FXML private lateinit var prijmeniTextField: TextField @FXML private lateinit var emailTextField: TextField @FXML private lateinit var telefonTextField: TextField @FXML private lateinit var datumPicker: DatePicker }
Metody pro obsluhu tlačítek
Dále si připravíme metodu pro načtení obrázku:
@FXML private fun nacistObrazek() { val fileChooser = FileChooser() // Vytvoření průzkumníka souborů val soubor: File = fileChooser.showOpenDialog(Stage()) // Otevření dialogového okna průzkumníka souborů val obrazekURL: URL = soubor.toURI().toURL() // Vytvoření URL cesty k souboru val obrazek = Image(obrazekURL.toExternalForm()) // Získání obrázku - .png, .jpg, .jpeg... obrazekView.image = obrazek // Zobrazení vybraného obrázku }
Pomocí metody FileChooser()
vytvoříme průzkumníka souborů,
který nám následně umožní vybrat soubor s obrázkem. Do pomocné
proměnné si uložíme cestu k obrázku, který následně vytvoříme pomocí
třídy Image()
. Nakonec jej zobrazíme v našem formuláři.
Doplníme také metodu, která bude sloužit k ukládání uživatelů:
@FXML private fun ulozZaznam() { val jmeno = jmenoTextField.text val prijmeni = prijmeniTextField.text val email = emailTextField.text val telCislo = telefonTextField.text /** * Nejdříve získáme hodnotu z DatePicker novyUzivatelDatumRegistrace, * Poté získáme den, měsíc a rok. Nakonec vytvoříme datum ve formátu "den'.'Měsíc'.'Rok" */ val datePickerValue = datumPicker.value val den = datePickerValue.dayOfMonth.toString() val mesic = datePickerValue.monthValue.toString() val rok = datePickerValue.year.toString() val datum = "${den}.${mesic}.${rok}" val datumNarozenin: LocalDate = LocalDate.parse(datum, DateTimeFormatter.ofPattern("d'.'M'.'y")) val uzivatel = Zamestnanec(jmeno, prijmeni, email, telCislo, datumNarozenin) // Vytvoření nového zaměstnance val obrazek = obrazekView.image uzivatel.obrazek = SwingFXUtils.fromFXImage( obrazek, null ) // SwingFXUtils - Přeloží JavaFX Image do BufferedImage zamestnanci.add(uzivatel) val fileChooser = FileChooser() // Vytvoření průzkumníku souborů fileChooser.title = "Uložit soubor" fileChooser.extensionFilters.addAll(FileChooser.ExtensionFilter("All Files", "*.*")) val soubor = fileChooser.showSaveDialog(Stage()) }
Kód obou metod by měl být srozumitelný, za zmínku stojí použití
SwingFXUtils
pro převedení obrázku do formátu
BufferedImage
.
Přejděme tedy k poslední metodě pro obsluhu tlačítek našeho
formuláře pro načítání záznamů. V metodě nacistZaznam()
bude možné vybrat soubor, který chceme načíst a poté zavoláme metodu
zobrazUzivatele()
, kterou si vzápětí doplníme:
@FXML private fun nacistZaznam() { val fileChooser = FileChooser() // Vytvoření průzkumníku souborů val soubor: File = fileChooser.showOpenDialog(Stage()) // Otevření dialogového okna průzkumníka souborů zobrazUzivatele() }
Metoda zobrazUzivatele()
Po načtení souboru necháme ve formuláři vypsat uživatele, který byl do kolekce uložen jako první:
private fun zobrazUzivatele(){ jmenoTextField.text = zamestnanci.get(0).jmeno prijmeniTextField.text = zamestnanci.get(0).prijmeni emailTextField.text = zamestnanci.get(0).email datumPicker.value = zamestnanci.get(0).narozeniny telefonTextField.text = zamestnanci.get(0).telefon obrazekView.image = SwingFXUtils.toFXImage(zamestnanci.get(0).obrazek, null) // Pomocí SwingFXUtils opět přeložíme BufferedImage pro zobrazení v JavaFX }
Nyní máme aplikaci navrženou. Samotné ukládání a načítání ZIP archivu si ukážeme a doplníme příště.
V příští lekci, Práce s vlastními soubory v Kotlin - XML pro ZIP archiv, budeme pokračovat v přípravě formulářové aplikace pro ukládání a načítání ZIP souborů. Doplníme si do ní třídy pro zpracování údajů o zaměstnancích v XML formátu.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 3x (37.34 kB)
Aplikace je včetně zdrojových kódů v jazyce Kotlin