Lekce 19 - Práce s vlastními soubory v Javě - Zip archiv
V minulé lekci, Práce se soubory a složkami v Javě - Nové API, jsme si ukázali práci se soubory a složkami v Javě.
Nyní již umíte pracovat se spoustou druhů souborů, umíte je ukládat a otevírat, přehrávat, odchytávat chyby, ... Představte si ovšem reálnou aplikaci k evidenci zaměstnanců. Zaměstnanec bude mít 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 binární soubory poměrně nešikovné a špatně se s nimi reaguje na změny formátu.
Zip
Podobné aplikace často využívají k ukládání dat archivy. Vezměte si
takový MS-Word a jeho dokumenty s příponou souborů .docx. Když
změníte příponu libovolného .docx souboru na
.zip, zjistíte, ž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íte jen
Dokument. Nastavení změníte v Ovládacích panelech ->
Zobrazit podle: Ikony -> Možnosti složky -> Zrušit zatržítko Skrýt
přípony známých typů.
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í ze
.zamestnanec nebo pokud se chcete držet třípísmenných, tak jen
.zam.
Přípona souboru totiž 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ž 3 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 by mohla být následující:
data.zamzamestnanci.xmlobrazky/jmenoprijmeni_1.pngjmenoprijmeni_2.png
Soubor zamestnanci.xml by mohl vypadat následovně:
<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 Zamestnanec
Vytvořte 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é - vlastnostmi. Náš zaměstnanec bude mít:
- jméno,
- příjmení,
- email,
- telefon,
- datum narození
- a bude mít i fotografii:
public class Zamestnanec { private String jmeno; private String prijmeni; private String email; private String telefon; private LocalDate narozeniny; private BufferedImage obrazek; public Zamestnanec() { this("", "", "", "", LocalDate.now()); } public Zamestnanec(String jmeno, String prijmeni, String email, String telefon, LocalDate narozeniny) { this.jmeno = jmeno; this.prijmeni = prijmeni; this.email = email; this.telefon = telefon; this.narozeniny = narozeniny; } @Override public String toString() { return "Zamestnanec{" + "jmeno=" + jmeno + ", prijmeni=" + prijmeni + '}'; } }
Třída má dva konstruktory. První přetížení vytvoří prázdného zaměstnance. Pomocí druhého konstruktoru vytvoříme instanci zaměstnance se všemi údaji, kromě obrázku.
Gettery a settery
Dále následují pouze gettery a settery pro tyto vlastnosti:
public String getJmeno() { return jmeno; } public void setJmeno(String jmeno) { this.jmeno = jmeno; } public String getPrijmeni() { return prijmeni; } public void setPrijmeni(String prijmeni) { this.prijmeni = prijmeni; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getTelefon() { return telefon; } public void setTelefon(String telefon) { this.telefon = telefon; } public LocalDate getNarozeniny() { return narozeniny; } public void setNarozeniny(LocalDate narozeniny) { this.narozeniny = narozeniny; } public BufferedImage getObrazek() { return obrazek; } public void setObrazek(BufferedImage obrazek) { this.obrazek = obrazek; }
Do formuláře si přidáme proměnnou typu Zamestnanec, ale
nebudeme ji instancovat:
private Zamestnanec zamestnanec;
Správce zaměstnanců
Abychom dodrželi oddělení logiky a GUI, založíme si novou třídu,
která se bude starat o správu zaměstnanců. Třídu nazvěme jednoduše
SpravceZamestnancu. Třída bude obsahovat kolekci zaměstnanců.
Kolekce bude typu DefaultListModel, abychom ji později mohli
využít pro více zaměstnanců.
private final DefaultListModel<Zamestnanec> zamestnanci = new DefaultListModel<>();
Dále vytvoříme ve třídě čtyři metody: uloz(),
nacti(), vratPrvniho() a ulozPrvniho().
Metody uloz() a nacti() budeme implementovat až v
následující lekci. Poslední dvě metody tu máme pouze pro jednoduchost,
abychom mohli pracovat s jedním zaměstnancem. Jejich implementace bude
následující:
public Zamestnanec vratPrvniho() { return zamestnanci.size() == 0 ? new Zamestnanec() : zamestnanci.get(0); } public void ulozPrvniho(Zamestnanec zamestnanec) { this.zamestnanci.clear(); this.zamestnanci.addElement(zamestnanec); }
Úprava formuláře
To by bylo prozatím ve správci vše. Přesuňme se ještě rychle do
formuláře, kde vytvoříme instanci správce a necháme si od něj instancovat
třídu Zamestnanec:
private final SpravceZamestnancu spravce = new SpravceZamestnancu(); private Zamestnanec zamestnanec = spravce.vratPrvniho();
Dále do kódu formuláře přidáme dvě pomocné metody, pomocí kterých
budeme aktualizovat údaje na formuláři a v instanci třídy
Zamestnanec:
private void aktulizujFormular() { jTxtName.setText(zamestnanec.getJmeno()); jTxtSurname.setText(zamestnanec.getPrijmeni()); jTxtEmail.setText(zamestnanec.getEmail()); jTxtPhoneNumber.setText(zamestnanec.getTelefon()); jTxtBirthday.setText(Konstanty.FORMAT_DATA.format(zamestnanec.getNarozeniny())); jPanel1.getGraphics().drawImage(zamestnanec.getObrazek(), 0, 0, 123, 135, null); } private void nactiZFormulare() { zamestnanec.setJmeno(jTxtName.getText()); zamestnanec.setPrijmeni(jTxtSurname.getText()); zamestnanec.setEmail(jTxtEmail.getText()); zamestnanec.setTelefon(jTxtPhoneNumber.getText()); zamestnanec.setNarozeniny(LocalDate.parse(jTxtBirthday.getText(), Konstanty.FORMAT_DATA)); }
Obsluha tlačítek
Nakonec se podíváme na handlery tlačítek.
Výběr obrázku
První handler, na který se zaměříme, je obsluha tlačítka pro výběr obrázku:
private void jBtnImageActionPerformed(java.awt.event.ActionEvent evt) { nactiZFormulare(); JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileFilter(new FileNameExtensionFilter("Obrázky...", "png")); final int result = fileChooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { final File obrazek = fileChooser.getSelectedFile(); try { zamestnanec.setObrazek(ImageIO.read(obrazek)); aktulizujFormular(); } catch (IOException e) { e.printStackTrace(); } } }
Nejdříve uložíme případné hodnoty z komponent do instance třídy
Zamestnanec. Dále vytvoříme nový JFileChooser
dialog, pomocí kterého vybereme obrázek uživatele. Pokud obrázek vybereme
úspěšně, metodou ImageIO.read() načteme obrázek a uložíme
ho do zaměstnance. Nakonec zavoláme metodu aktualizujFormular(),
pomocí které zobrazíme obrázek na formuláři.
Uložení
Obsluha tlačítka pro uložení dat bude vypadat následovně:
private void jBtnSaveActionPerformed(java.awt.event.ActionEvent evt) { JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileFilter(new FileNameExtensionFilter("Soubory zaměstnanců...", "zam")); final int result = fileChooser.showSaveDialog(this); if (result == JFileChooser.APPROVE_OPTION) { final File souborZamestnancu = fileChooser.getSelectedFile(); try { nactiZFormulare(); spravce.ulozPrvniho(zamestnanec); spravce.uloz(souborZamestnancu); } catch (IOException | XMLStreamException e) { e.printStackTrace(); } } }
Pomocí JFileChooser dialogu vybereme soubor, do kterého chceme
uložit naše data. Pokud soubor vybereme, načteme data z formuláře do
instance zaměstnance. Tuto instanci předáme do správce, aby si uložil data.
Nakonec metodou uloz() zapíšeme veškerá data do souboru.
Načtení
Nakonec si ukážeme metodu pro načtení dat:
private void jBtnLoadActionPerformed(java.awt.event.ActionEvent evt) { JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileFilter(new FileNameExtensionFilter("Soubory zaměstnanců...", "zam")); final int result = fileChooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { final File souborZamestnancu = fileChooser.getSelectedFile(); try { spravce.nacti(souborZamestnancu); zamestnanec = spravce.vratPrvniho(); aktulizujFormular(); } catch (IOException | ParserConfigurationException | SAXException e) { e.printStackTrace(); } } }
V metodě opět zobrazíme JFileChooser dialog pro výběr
zaměstnanců. Pokud zvolíme soubor, zavoláme metodu nacti() nad
instanci třídy SpravceZamestnancu. Po úspěšném načtení
zobrazíme data prvního zaměstnance na formulář.
Nyní máme aplikaci navrženou.
V následujícím kvízu, Kvíz - Práce se soubory a složkami v Javě, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.
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 66x (43.15 kB)
Aplikace je včetně zdrojových kódů v jazyce Java
