4. díl - Uložení objektů do CSV v C#

C# .NET Práce se soubory Uložení objektů do CSV v C#

ONEbit hosting 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ém dílu seriálu tutoriálů o C# 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 nový projekt typu Windows Forms Application. Přidáme si k němu 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:

class Uzivatel
{
        public string Jmeno { get ; private set; }
        public int Vek { get; private set; }
        public DateTime Registrovan { get; private set; }

        public Uzivatel(string jmeno, int vek, DateTime registrovan)
        {
                Jmeno = jmeno;
                Vek = vek;
                Registrovan = registrovan;
        }

        public override string ToString()
        {
                return Jmeno;
        }

}

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 List. 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
{
        private List<Uzivatel> uzivatele;
        private string soubor;

        public Databaze(string soubor)
        {
        }

        public void PridejUzivatele(string jmeno, int vek, DateTime registrovan)
        {
        }

        public Uzivatel[] VratVsechny()
        {
        }

        public void Uloz()
        {
        }

        public void Nacti()
        {
        }
}

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

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

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

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

public void PridejUzivatele(string jmeno, int vek, DateTime registrovan)
{
        Uzivatel u = new Uzivatel(jmeno, vek, registrovan);
        uzivatele.Add(u);
}

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 Uzivatel[] VratVsechny()
{
        return uzivatele.ToArray();
}

Uložení uživatelů do CSV

Nyní se konečně dostáváme k práci s CSV souborem. Začneme using blokem s instancí StreamWriteru. 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()
{
        // otevření souboru pro zápis
        using (StreamWriter sw = new StreamWriter(soubor))
        {
                // projetí uživatelů
                foreach (Uzivatel u in uzivatele)
                {
                        // vytvoření pole hodnot
                        string[] hodnoty = { u.Jmeno, u.Vek.ToString(), u.Registrovan.ToShortDateString() };
                        // vytvoření řádku
                        string radek = String.Join(";", hodnoty);
                        // zápis řádku
                        sw.WriteLine(radek);
                }
                // vyprázdnění bufferu
                sw.Flush();
        }
}

Kdybychom u data registrace ponechali jen ToString(), uložil by se nám i čas, což zde není příhodné. Pojďme si vše vyzkoušet, přejděme k souboru Formuláře (Form1.cs, případně v designeru F7). 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 Form1()
{
        InitializeComponent();
        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 C#

V jeho Click handleru (vytvoří se 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 tlacitkoUlozit_Click(object sender, EventArgs e)
{
        databaze.PridejUzivatele("Pavel Slavík", 22, new DateTime(2000, 3, 21));
        databaze.PridejUzivatele("Jan Novák", 31, new DateTime(2012, 10, 30));
        databaze.Uloz();
}

Aplikaci spustíme a klikneme na tlačítko. Nyní otevřeme (např. v NotePadu) soubor uzivatele.csv (ve složka s projektem/bin/debug) 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ě.


 

 

Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
9 hlasů
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Miniatura
Předchozí článek
Práce s textovými soubory v C#
Miniatura
Všechny články v sekci
Práce se soubory v C#
Miniatura
Následující článek
Uložení objektů do CSV v C# část 2
Aktivity (3)

 

 

Komentáře
Zobrazit starší komentáře (26)

Avatar
Michal Štěpánek:21.4.2016 21:29

Trošku to upřesni, jak často chceš data měnit, přidávat, mazat, jak často se v nich chceš vrtat, vyhledávat, kolik jich cca může být celkem, co se s nimi má dít po uložení, nebo po načtení, atd...
Podle toho se pak odvíjí způsoby ukládání dat.

Odpovědět 21.4.2016 21:29
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
lukas.kotyza
Člen
Avatar
Odpovídá na Michal Štěpánek
lukas.kotyza:21.4.2016 22:52

No potřeboval bych je načíst při otevření do numericupdownu, data změnit, uložit a zavřít to je vše

PS:nejlepší by bylo kdyby se uložili po každé změně ale to není nutné

 
Odpovědět 21.4.2016 22:52
Avatar
Odpovídá na lukas.kotyza
Michal Štěpánek:21.4.2016 23:55

V tom případě je úplně šumák, jestli použiješ csv, txt nebo xml

Odpovědět 21.4.2016 23:55
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
lukas.kotyza
Člen
Avatar
 
Odpovědět 22.4.2016 17:11
Avatar
LittleBigOwl
Člen
Avatar
LittleBigOwl:30.12.2016 12:24

V metóde ulož by malo byť asi uloženie do súboru: @"soubor.csv" (teraz tam máš txt, takže sa to uloží do txt.) Ak to tak nie, tak prosím o vysvetlenie. Inak Ďakujem za tutoriály, sú super.

 
Odpovědět 30.12.2016 12:24
Avatar
LittleBigOwl
Člen
Avatar
LittleBigOwl:30.12.2016 12:37

Urobil som to presne podľa tutoriálu, ale nerobil som to vo Win Forms ale vo WPF, a tam sa ten subor uzivatele.csv nevytvorí, vytvorí sa len soubor.txt. Tak neviem či robím niekde chybu ja, či to bude tým WPF.

 
Odpovědět 30.12.2016 12:37
Avatar
Odpovídá na LittleBigOwl
Michal Štěpánek:30.12.2016 22:54

WPFkem to určitě nebude. Stáhni si přiložený soubor a zkontroluj si, kde máš chybku...

Odpovědět 30.12.2016 22:54
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Lukas C#
Redaktor
Avatar
Odpovídá na LittleBigOwl
Lukas C#:31.12.2016 9:28

Přípona je jenom součástí jména souboru. Mohlo by tam být klidně i ".abcd". O formátu rozhoduje metoda StreamWriter.Wri­teLine(), která zapíše čistý text.

Takže formálně: Formát souboru je "plain-text", a způsob uložení dat je "comma-separated-values" - text, kde jsou hodnoty dělené čárkou, aby se daly snadno načítat a parsovat.

 
Odpovědět 31.12.2016 9:28
Avatar
ostrozan
Redaktor
Avatar
Odpovídá na LittleBigOwl
ostrozan:31.12.2016 16:22

Být tebou tak tady nad tím moc nedumám, protože nevím jak ostatní ale já používám výhradně třídu FileStream a její metody - je jich spousta - m.j. asynchronní čtení-zápis dat - nutné u větších objemů dat a spoustu dalších

navíc si můžeš jakýkoliv soubor vytvořit metodou File.Create("ces­ta\k\tvemu\sou­boru.csv");

 
Odpovědět  +1 31.12.2016 16:22
Avatar
LittleBigOwl
Člen
Avatar
Odpovídá na ostrozan
LittleBigOwl:4. ledna 15:12

Ďakujem krásne všetkým za vysvetlenie a rady a prajem všetko dobré do nového roku.

 
Odpovědět  +1 4. ledna 15:12
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 10 zpráv z 36. Zobrazit vše