19. diel - Práca s vlastnými súbormi v Jave - Zip archív
V minulej lekcii, Práca so súbormi a priečinkami v Jave - Nové API, sme si ukázali prácu so súbormi a priečinkami v Jave.
Teraz už viete pracovať s množstvom druhov súborov, viete ich ukladať a otvárať, prehrávať, odchytávať chyby, ... Predstavte si však reálnu aplikáciu na evidenciu zamestnancov. Zamestnanec bude mať textové údaje (meno, priezvisko a email), dátum (dátum narodenia), číslo (telefónne číslo) a obrázok (fotografiu). Už len kvôli obrázku môže byť na prvý pohľad problém všetky tieto dáta uložiť a to ideálne do jedného jediného súboru. Teoreticky by sme mohli zvoliť nejaký binárny formát dát (kvôli obrázku) a vložiť do neho aj textové údaje. Prakticky sú binárne súbory pomerne nešikovné a zle sa s nimi reaguje na zmeny formátu.
Archív zip
Podobné aplikácie často využívajú na ukladanie dát archívy. Vezmite
si taký MS-Word a jeho dokumenty s príponou súborov .docx
. Keď
zmeníte príponu ľubovoľného .docx
súboru na
.zip
, zistíte, že dokument je v skutočnosti archív zip, iba s
inou príponou. Skúste si to.
Windows skrývajú v predvolenom nastavení prípony súborov
známych typov, takže namiesto Document.docx
vidíte len
Document
. Nastavenie zmeníte v ovládacom paneli, tu kliknite na
View > Show > File name extension.
Ako archív v sebe môže súbor obsahovať jednoducho niekoľko súborov a
navonok sa tvári pre nič netušiaceho užívateľa ako jeden. Presne archívu
zip využijeme aj na uloženie nášho zamestnanca. A namiesto .zip
nastavíme súboru úplne inú príponu, ponúka sa .employee
alebo
ak sa chcete držať trojpísmenných, tak len .emp
.
Prípona súboru totiž slúži len na to, aby operačný systém Windows
zistil, v akej aplikácii má súbor otvoriť, keď naň používateľ poklepe.
Väčšinou platí, že má každý súbor na konci svojho názvu bodku a
trojpísmenovú príponu. V skutočnosti nemusí mať súbor príponu vôbec
žiadnu, môže ich mať viac, môžu byť dlhšie ako tri znaky a dokonca
nemusia vôbec zodpovedať tomu, čo je v súbore uložené. My budeme súbor
.zip
maskovať ako súbor .emp
. Zip neponecháme z
toho dôvodu, aby to používateľa nesmiatlo a nezačal súbory rozbaľovať a
meniť.
Formát súborov .emp
Štruktúra zazipovanej zložky by mohla byť nasledovná:
data.emp |-- employees.xml |-- images/ |-- firstnamelastname_1.png |-- firstnamelastname_2.png
Súbor employees.xml
by mohol vyzerať nasledovne:
<employees> <employee> <firstName>Thomas</firstName> <lastName>Cooper</lastName> <email>[email protected]</email> <phone>123456789</phone> <birthdate>1/1/1970</birthdate> </employee> </employees>
Element <employees>
obaľujúci zamestnancov
je tu preto, že aplikácia môže niekedy v budúcnosti spracovávať viac
zamestnancov. Nad takými "drobnosťami" je potrebné pri návrhu
premýšľať.
Tvorba aplikácie
Employees
Vytvorte si nový projekt, formulárovú aplikáciu. Pod článkom je k dispozícii archív s projektom. V projekte už sú vygenerované všetky potrebné formulárové prvky a navesené obsluhy tlačidiel:
Trieda Employee
Začneme tým, čo by malo byť jasné - vlastnosťami. Náš zamestnanec bude mať:
- meno,
- priezvisko,
- email,
- telefón,
- dátum narodenia
- a bude mať aj fotografiu:
public class Employee { private String firstName; private String lastName; private String email; private String phone; private LocalDate birthdate; private BufferedImage image; public Employee() { this("", "", "", "", LocalDate.now()); } public Employee(String firstName, String lastName, String email, String phone, LocalDate birthdate) { this.firstName = firstName; this.lastName = lastName; this.email = email; this.phone = phone; this.birthdate = birthdate; } @Override public String toString() { return "Employee{" + "first name=" + firstName + ", last name=" + lastName + '}'; } }
Trieda má dva konštruktory. Prvé preťaženie vytvorí prázdneho zamestnanca. Pomocou druhého konštruktora vytvoríme inštanciu zamestnanca so všetkými údajmi, okrem obrázku.
Gettery a settery
Ďalej nasledujú iba gettery a settery pre tieto vlastnosti:
public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public LocalDate getBirthdate() { return birthdate; } public void setBirthdate(LocalDate birthdate) { this.birthdate = birthdate; } public BufferedImage getImage() { return image; } public void setImage(BufferedImage image) { this.image = image; }
Do formulára si pridáme premennú typu Employee
, ale nebudeme
ju inštancovať:
private Employee employee;
Správca zamestnancov
Aby sme dodržali oddelenie logiky a GUI, založíme si novú triedu, ktorá
sa bude starať o správu zamestnancov. Triedu nazvime jednoducho
EmployeeManager
. Trieda bude obsahovať kolekciu zamestnancov.
Kolekcia bude typu DefaultListModel
, aby sme ju neskôr mohli
využiť pre viacerých zamestnancov.
private final DefaultListModel<Employee> employees = new DefaultListModel<>();
Ďalej vytvoríme v triede štyri metódy: save()
,
load()
, getFirst()
a saveFirst()
. Metódy
save()
a load()
budeme implementovať až v
nasledujúcej lekcii. Posledné dve metódy tu máme iba pre jednoduchosť, aby
sme mohli pracovať s jedným zamestnancom. Ich implementácia bude
nasledovná:
public Employee getFirst() { return employees.size() == 0 ? new Employee() : employees.get(0); } public void saveFirst(Employee employee) { this.employees.clear(); this.employees.addElement(employee); }
Úprava formulára
To by bolo zatiaľ v správcovi všetko. Presuňme sa ešte rýchlo do
formulára, kde vytvoríme inštanciu správcu a necháme si od neho
inštancovať triedu Employee
:
private final EmployeeManager manager = new EmployeeManager(); private Employee employee = manager.getFirst();
Ďalej do kódu formulára pridáme dve pomocné metódy, pomocou ktorých
budeme aktualizovať údaje na formulári a v inštancii triedy
Employee
:
private void refreshForm() { jTxtFirstName.setText(employee.getFirstName()); jTxtLastName.setText(employee.getLastName()); jTxtEmail.setText(employee.getEmail()); jTxtPhoneNumber.setText(employee.getPhone()); jTxtBirthday.setText(Constants.FORMAT_DATA.format(employee.getBirthdate())); jPanel1.getGraphics().drawImage(employee.getImage(), 0, 0, 123, 135, null); } private void loadFromForm() { employee.setFirstName(jTxtFirstName.getText()); employee.setLastName(jTxtLastName.getText()); employee.setEmail(jTxtEmail.getText()); employee.setPhone(jTxtPhoneNumber.getText()); employee.setBirthdate(LocalDate.parse(jTxtBirthday.getText(), Constants.FORMAT_DATA)); }
Obsluha tlačidiel
Nakoniec sa pozrieme na handlery tlačidiel.
Výber obrázku
Prvý handler, na ktorý sa zameriame, je obsluha tlačidla pre výber obrázku:
imageButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileFilter(new FileNameExtensionFilter("Images...", "png")); final int result = fileChooser.showOpenDialog(form); if (result == JFileChooser.APPROVE_OPTION) { final File image = fileChooser.getSelectedFile(); try { employee.setImage(ImageIO.read(image)); refreshForm(); } catch (IOException ex) { ex.printStackTrace(); } } } });
Najskôr uložíme prípadné hodnoty z komponentov do inštancie triedy
Employee
. Ďalej vytvoríme nový JFileChooser
dialóg, pomocou ktorého vyberieme obrázok používateľa. Pokiaľ obrázok
vyberieme úspešne, metódou ImageIO.read()
načítame obrázok a
uložíme ho do zamestnanca. Nakoniec zavoláme metódu
refreshForm()
, pomocou ktorej zobrazíme obrázok na
formulári.
Uloženie
Obsluha tlačidla na uloženie dát bude vyzerať nasledovne:
saveButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileFilter(new FileNameExtensionFilter("Employee files...", "emp")); final int result = fileChooser.showSaveDialog(form); if (result == JFileChooser.APPROVE_OPTION) { final File employeeFile = fileChooser.getSelectedFile(); try { loadFromForm(); manager.saveFirst(employee); manager.save(employeeFile); } catch (IOException | XMLStreamException ex) { ex.printStackTrace(); } } } });
Pomocou JFileChooser
dialógu vyberieme súbor, do ktorého
chceme uložiť naše dáta. Ak súbor vyberieme, načítame dáta z formulára
do inštancie zamestnanca. Túto inštanciu odovzdáme do správcu, aby si
uložil dáta. Nakoniec metódou save()
zapíšeme všetky dáta do
súboru.
Načítanie
Nakoniec si ukážeme metódu na načítanie dát:
loadButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileFilter(new FileNameExtensionFilter("Employee files...", "emp")); final int result = fileChooser.showOpenDialog(form); if (result == JFileChooser.APPROVE_OPTION) { final File employeeFile = fileChooser.getSelectedFile(); try { manager.load(employeeFile); employee = manager.getFirst(); refreshForm(); } catch (IOException | ParserConfigurationException | SAXException ex) { ex.printStackTrace(); } } } });
V metóde opäť zobrazíme JFileChooser
dialóg pre výber
zamestnancov. Ak zvolíme súbor, zavoláme metódu load()
nad
inštanciu triedy EmployeeManager
. Po úspešnom načítaní
zobrazíme dáta prvého zamestnanca na formulár.
Teraz máme aplikáciu navrhnutú.
V nasledujúcom kvíze, Kvíz - Práca so súbormi a priečinkami v Jave, si vyskúšame nadobudnuté skúsenosti z predchádzajúcich lekcií.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 0x (8.72 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java