C a C++ týden ITnetwork Flashka zdarma
Akce! Pouze tento týden sleva až 80 % na kurzy C++. Lze kombinovat s akcí 50 % bodů navíc na prémiový obsah!
Brno? Vypsali jsme pro vás nové termíny školení Základů programování a OOP v Brně!

Lekce 4 - Uložení objektů do CSV v Javě

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Práce s textovými soubory v Javě, jsme si ukázali zápis do textových souborů i jejich čtení. Aplikace byla jednoduchá a spíše učebnicová. Udělejme si nyní opravdovou databázi uživatelů pomocí textových souborů. Ukládat budeme samozřejmě objekty, čili si program snadno předěláte na databázi upomínek v diáři, databázi nejlepších výsledků ve hře, databázi zvířat v chovné stanici nebo na cokoli, co budete potřebovat evidovat.

Formát CSV

Nebudeme vymýšlet žádný složitý způsob ukládání dat do textových souborů, protože již jeden osvědčený a standardní existuje. Jmenuje se CSV (jako Comma Separated Values), tedy hodnoty oddělené čárkou, případně středníkem. O CSV jsme se zmínili v článku o metodách split() a join() na řetězci, dnes je tedy budeme potřebovat.

Pojďme se shodnout na tom, jak bude třída uživatele vypadat. Následně si ukážeme, jak její instance do CSV uložíme. Založte si v NetBeans nový Java Swing projekt a vytvořte si nový JFrame. Samozřejmě můžete použít i JavaFX, pokud chcete. Dále vytvoříme třídu Uzivatel. U uživatele budeme evidovat jeho jméno, věk a datum, kdy byl registrován. Konstruktor bude instanci inicializovat na základě těchto 3 vlastností. Přepíšeme si metodu toString() tak, aby vrátila jméno uživatele. Třída tedy bude vypadat takto:

public class Uzivatel {

    private String jmeno;
    private int vek;
    private LocalDate registrovan;

    public Uzivatel(String jmeno, int vek, LocalDate registrovan) {
        this.jmeno = jmeno;
        this.vek = vek;
        this.registrovan = registrovan;
    }

    public String getJmeno() {
        return jmeno;
    }

    public int getVek() {
        return vek;
    }

    public LocalDate getRegistrovan() {
        return registrovan;
    }

    @Override
    public String toString() {
        return jmeno;
    }

}

Nezapomeňte si naimportovat LocalDate.

Pojďme si ukázat, jak budou uživatelé ve formátu CSV vypadat. Každý řádek bude reprezentovat jednoho uživatele. Vlastnosti uživatele budou odděleny středníky. Uživatel Pavel Slavík, kterému je 22 let a zaregistroval se 21.3.2000 by vypadal takto:

Pavel Slavík;22;21.3.2000

Na první pohled vidíme, že je soubor relativně jednoduše čitelný, i když nezasvěcený se může jen domnívat, co je číslo 22 a k čemu se váže ono datum.

V souboru může být samozřejmě více uživatelů, tedy více řádků.

Třídu uživatele máme, protože však ctíme objektový návrh, vytvoříme si i třídu pro naši databázi. Ta bude obsahovat kolekci uživatelů, tvořenou instancí třídy DefaultListModel. Tuto kolekci jsme zvolili proto, že ji později můžeme napojit na Swing ListView a zobrazovat tak naše uživatele ve formuláři. Kolekce bude privátní a přidávání uživatelů (případně jejich mazání, vyhledávání a podobně) bude realizováno veřejnými metodami. Databáze bude konečně obsahovat metody k načtení CSV souboru a také k uložení obsahu databáze do souboru. Jméno souboru bude další privátní atribut databáze. Přidejme si tedy k projektu další třídu Databaze a napišme její kostru:

class Databaze {

    DefaultListModel<Uzivatel> uzivatele;
    private String soubor;

    public Databaze(string soubor) {
    }

    public void pridejUzivatele(String jmeno, int vek, LocalDate registrovan) {
    }

    public List<Uzivatel> vratVsechny() {
    }

    public ListModel<Uzivatel> getModel() {
    }

    public void uloz() throws IOException {
    }

    public void nacti() throws IOException {
    }
}

NetBeans nám metodu vratVsechny() podtrhne červeně (protože nevrací hodnotu), stejně jako getModel(), ale toho si zatím nebudeme všímat. Pojďme postupně naimplementovat jednotlivé metody. Začněme konstruktorem.

V konstruktoru vytvoříme instanci ArrayListu a uložíme si cestu k databázovému souboru:

public Databaze(string soubor) {
    uzivatele = new DefaultListModel<>();
    this.soubor = soubor;
}

To bylo velmi jednoduché a i na další metodě není co vymýšlet:

public void pridejUzivatele(String jmeno, int vek, LocalDate registrovan) {
    Uzivatel u = new Uzivatel(jmeno, vek, registrovan);
    uzivatele.add(u);
}

Metoda getModel() pouze vrátí kolekci uživatelů:

public ListModel<Uzivatel> getModel() {
    return uzivatele;
}

Metoda vratVsechny() nám vrátí všechny uživatele. Podobně můžeme v budoucnu udělat metody pro vyhledávání jen některých uživatelů. Uživatele navrátíme ve formě pole:

public List<Uzivatel> vratVsechny() {
    return Collections.list(uzivatele.elements());
}

Uložení uživatelů do CSV

Nyní se konečně dostáváme k práci s CSV souborem. Začneme blokem try-catch with resources s instancí BufferedWriteru. Uvnitř proiterujeme náš list uživatelů a pro každého uživatele vytvoříme pole Stringů z jeho vlastností. Nestringové vlastnosti musíme na String explicitně převést. Pole poté spojíme na dlouhý String, ve kterém budou položky oddělené středníky. Spojení za nás vykoná metoda join(). Ta se narozdíl od metody split() volá přímo na třídě String a jako parametr (spojovací text) bere také String, nikoli char. Pusťme se do toho:

public void uloz() throws IOException {
    // Otevření souboru pro zápis
    try (BufferedWriter bw = new BufferedWriter(new FileWriter(soubor))) {
        // projetí uživatelů
        for (Uzivatel u : vratVsechny()) {
            // Vytvoření pole hodnot
            String[] hodnoty = {u.getJmeno(), String.valueOf(u.getVek()), u.getRegistrovan().toString()};
            // Vytvoření jednoho řádku
            String radek = String.join(";", hodnoty);
            // Zápis řádku
            bw.append(radek);
            // Zápis "enteru", abychom se dostali na nový řádek
            bw.append("\n");
        }
        // Vyprázdnění bufferu
        bw.flush();
    }
}

Pojďme si vše vyzkoušet, přejděme k souboru formuláře (MainJFrame.java). Zde vytvoříme privátní atribut databaze, do kterého v konstruktoru formuláře uložíme novou instanci naší databáze:

private Databaze databaze;

public MainJFrame() {
    initComponents();
    databaze = new Databaze("uzivatele.csv");
}

Na formulář přidejme nové tlačítko, pojmenujme ho tlacitkoUlozit a text mu nastavme na "Uložit".

Formulář pro uložení do CSV v Javě

V jeho Click handleru (metodě, co se vytvoří po dvojkliku na tlačítko) přidáme do databáze 2 uživatele. Bude to nyní pro vyzkoušení, později bude aplikace vypadat lépe. Dále celou databázi uložíme do souboru:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
    try {
        databaze.pridejUzivatele("Pavel Slavík", 22, LocalDate.of(2000, 3, 21));
        databaze.pridejUzivatele("Jan Novák", 31, LocalDate.of(2012, 10, 30));
        databaze.uloz();
    } catch (IOException ex) {
        JOptionPane.showMessageDialog(null, "Databázi se nepodařilo uložit, zkontrolujte přístupová práva k souboru.");
    }
}

Aplikaci spustíme a klikneme na tlačítko. Nyní otevřeme (např. v NotePadu) soubor uzivatele.csv (ve složce s projektem) a vidíme, že má následující obsah:

Pavel Slavík;22;21.3.2000
Jan Novák;31;30.10.2012

Vše tedy funguje, jak má :) Načtení uživatelů a dokončení aplikace si necháme na příští lekci, Uložení objektů do CSV v Javě část 2.


 

 

Článek pro vás napsal Petr Štechmüller
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
Autor se věnuje primárně programování v Jave, ale nebojí se ani webových technologií.
Předchozí článek
Práce s textovými soubory v Javě
Všechny články v sekci
Práce se soubory v Javě
Miniatura
Následující článek
Uložení objektů do CSV v Javě část 2
Aktivity (4)

 

 

Komentáře

Avatar
Pavol Franek
Člen
Avatar
Pavol Franek:5. května 19:07

Písali si že vlastnosti užívateľa budú oddelené "středníky".

Pavel Slavík;22;21.3.2000

No v metóde uloz() si pužil join s čiarkou:

String radek = String.join(",", hodnoty);
 
Odpovědět 5. května 19:07
Avatar
Petr Štechmüller
Překladatel
Avatar
Odpovídá na Pavol Franek
Petr Štechmüller:5. května 20:20

Díky, poslal jsem opravu ke schválení.

Odpovědět 5. května 20:20
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.