NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
IT rekvalifikace s podporou uplatnění. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!

Lekce 10 - Serializace a deserializace v C# .NET

V minulé lekci, LINQ to XML v C# .NET, jsme se naučili generovat, číst, editovat a mazat data v XML souborech pomocí technologie LINQ to XML.

V C# .NET tutoriálu budeme konvertovat objekt na proud bytů, který převedeme zpět na kopii objektu. Naučíme se tedy serializovat a deserializovat objekt.

Úvod do serializace a deserializace

Serializace je uchování stavu objektu. Trochu odborněji by se to dalo popsat jako konvertování objektu na proud bytů a poté uložení někde do paměti, databáze nebo souboru. Deserializace je opak serializace. Dalo by se říci, že tedy převedeme proud bytů zpět na kopii objektu.

Využití

Serializace nám umožnuje uložit stav objektu a potom pomocí deserializace si ho kdykoliv znovu vytvořit. Pomocí serializace se třeba posílají data skrz síť nebo se ukládá nastavení aplikace.

Serializace

Než se pustíme do vlastní konverze objektu na proud bytů, připravíme si aplikaci. Založme si aplikaci typu Windows Forms Application s názvem SerializaceDeserializace.

Třída Uzivatel

Do aplikace si přidáme tuto veřejnou třídu Uzivatel, jejíž instance budeme chtít zachovat:

[Serializable()]
public class Uzivatel
{
    [XmlAttribute("Jméno")]
    public string Jmeno { get; set; }

    [XmlAttribute("Přijmení")]
    public string Prijmeni { get; set; }

    [XmlAttribute("DatumNarození")]
    public DateTime DatumNarozeni { get; set; }

    public override string ToString()
    {
        return "Jméno: " + Jmeno +
               "Přijmení: " + Prijmeni +
               "Datum Narození: " + DatumNarozeni.ToShortDateString();
    }

}

Třídu anotujeme atributem [Serializable()], kterým říkáme, že její instance budeme chtít serializovat. Dále přidáme vlastnosti:

  • Jmeno,
  • Prijmeni,
  • DatumNarozeni.

Všechny vlastnosti anotujeme atributem [XmlAttribute("Name")], který změní XML element z párového na nepárový a hodnota dané vlastnosti bude v atributu Name. Například <Uzivatel Name="Jan"> místo <Jmeno>Jan</Jmeno>. Nakonec přepíšeme metodu ToString().

Kdybychom měli ve třídě vlastnost, kterou bychom nechtěli serializovat, anotovali bychom ji atributem [XmlIgnore].

Hlavní formulář

Ukažme si podobu hlavního formuláře, který si v zápětí popíšeme:

Pojmenování komponent ukázkové aplikace na serializaci ve Visual Studio - Soubory v C# .NET

Na hlavní formulář si přidáme:

  • Dva prvky TextBoxs názvem tbJmeno a tbPrijmeni na jméno a příjmení.
  • Prvek DateTimePicker s názvem dateTimePicker pro datum narození.
  • Tlačítko s názvem btnPridej pro přidání uživatele do naší aplikace.
  • Prvek ListBox s názvem listBoxUzivatele pro zobrazení uživatelů.

Ovládací prvky jsme si přejmenovali z vygenerovaných názvů na takové názvy, v kterých se vyznáme.

Kód hlavního formuláře

Přesuneme se do kódu hlavního formuláře, kam budeme psát veškerý další kód.

Kolekce uživatelů

Před vygenerovaným konstruktorem si vytvoříme privátní kolekci uzivatele typu List<Uzivatel>:

private List<Uzivatel> uzivatele = new List<Uzivatel>();

Obslužná metoda prvku btnPridej

Přesuneme se do designeru hlavního formuláře, kde si přidáme metodu k události Click ovládacího prvku btnPridej. V kódu hlavního formuláře si dopíšeme tělo vygenerované obslužné metody prvku btnPridej:

private void BtnPridej_Click(object sender, EventArgs e)
{
    Uzivatel uzivatel = new Uzivatel
    {
        Jmeno = tbJmeno.Text,
        Prijmeni = tbPrijmeni.Text,
        DatumNarozeni = dateTimePicker.Value
    };

    uzivatele.Add(uzivatel);

    listBoxUzivatele.DataSource = null;
    listBoxUzivatele.DataSource = uzivatele;
}

Nejprve vytvoříme nového uživatele s daty z našich kontrolek. Pak ho přidáváme do naší kolekce uzivatele. Nakonec ještě musíme obnovit zdroj dat našeho uživatele v prvku listBoxUzivatele. K tomu nám poslouží vlastnost DataSource.

Testování

Spusťme si aplikaci. Zkusme si přidat jen jednoho uživatele, abychom si byli jisti, že nám aplikace funguje.

Serializace dat

Nyní konečně můžeme přejít k serializaci dat. V kódu hlavního formuláře si napíšeme metodu Serializuj():

private void Serializuj()
{
    try
    {
        XmlSerializer serializer = new XmlSerializer(uzivatele.GetType());

        using (StreamWriter sw = new StreamWriter("uzivatele.xml"))
        {
            serializer.Serialize(sw, uzivatele);
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

V bloku try vytvoříme instanci serializer typu XmlSerializer na kolekci typu List<Uzivatel>. Poté vytvoříme stream sw typu StreamWriter, pomocí kterého budeme serializovat. Poté voláme metodu Serialize(), které:

  • v prvním parametru předáme náš stream sw,
  • v druhém parametru předáme naši kolekci uzivatele, jejíž data chceme serializovat.

V bloku catch vypíšeme případnou vzniklou vyjímku.

Nyní se vrátíme zpátky do designeru. U formuláře najdeme Event (událost) OnClosing, na kterou dvakrát klikneme. Ve vygenerované metodě v kódu hlavního formuláře zavoláme naší metodu Serializuj():

private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
    Serializuj();
}

Název vygenerované metody se může lišit podle názvu hlavního formuláře. Jestli jste jeho jméno neupravovali, budete mít na začátku prefix Form1.

Testování

Spusťme aplikaci, přidejme nějaké uživatele a poté aplikaci zavřeme. Kolekce uživatelů se serializuje a uloží do složky s aplikací na cestě .../bin/Debug/uzivatele.xml. Když soubor otevřeme, uvidíme zapsaná data:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfUzivatel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Uzivatel>
    <Jmeno>Jan</Jmeno>
    <Prijmeni>Novák</Prijmeni>
    <DatumNarozeni>2013-07-11T17:27:19</DatumNarozeni>
  </Uzivatel>
  <Uzivatel>
    <Jmeno>Jakub</Jmeno>
    <Prijmeni>Špatný</Prijmeni>
    <DatumNarozeni>2013-07-11T17:27:19</DatumNarozeni>
  </Uzivatel>
</ArrayOfUzivatel>

Deserializace dat

Serializaci máme, tak teď ještě deserializaci. Z pohledu na kód je to trošku těžší a proto si raději všechno vysvětlíme ještě jednou. Nejprve si do kódu hlavního formuláře napíšeme metodu Deserializuj():

private void Deserializuj()
{
    try
    {
        if (File.Exists("uzivatele.xml"))
        {
            XmlSerializer serializer = new XmlSerializer(uzivatele.GetType());
            using (StreamReader sr = new StreamReader("uzivatele.xml"))
            {
                uzivatele = (List<Uzivatel>)serializer.Deserialize(sr);
            }
        }
        else throw new FileNotFoundException("Soubor nebyl nalezen");
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Nejprve musíme zjistit, jestli vůbec daný XML soubor s daty existuje. K tomu nám poslouží třída File a její metoda Exists(string path), která vrací hodnotu typu bool. V těle podmínky vytvoříme serializer typu XmlSerializer na typ List naší kolekce uživatelů.

Dále vytvoříme StreamReader s cestou k našemu souboru. Pak zavoláme metodu Deserialize() ze třídy XmlSerializer. Je tu ale drobný detail, a to že metoda Deserialize() vrací object. Musíme zde tedy přetypovat na List<Uzivatel>, než přiřadíme uložené uživatele k našim stávajícím.

Nyní přejdeme do designeru hlavního formuláře. Ve vlastnostech (properties) formuláře najdeme událost Load, k níž si necháme vygenerovat obslužnou metodu, jejíž tělo vyplníme následovně:

private void FormMain_Load(object sender, EventArgs e)
{
    Deserializuj();
    listBoxUzivatele.DataSource = uzivatele;
}

Název vygenerované metody se může lišit podle názvu hlavního formuláře. Jestli jste jeho jméno neupravovali, budete mít na začátku prefix Form1.

V těle metody zavoláme naší metodu Deserializuj(). Poté ještě načteme naše uživatele do našeho prvku ListBox.

Testování

Spustíme aplikaci, naplníme kolekci daty a aplikaci zavřeme. Poté ji znovu otevřeme a uvidíme, že obsahuje všechny uživatele, které jsme tam přidali:

Výpis uzivatelů deserializací - Soubory v C# .NET

Závěr

Třída, kterou serializujeme, musí obsahovat bezparametrický konstruktor, nebo žádný parametrický. Je to z toho důvodu, že deserializer si nejdříve vytvoří prázdnou instanci a potom postupně zadává vlastnosti, jak je čte ze souboru nebo jiného streamu. Nemůžeme serializovat ovládací prvky, ať již defaultní nebo námi vytvořené (User Control).

V následujícím cvičení, Řešené úlohy k 6.-10. lekci práce se soubory v C# .NET, si procvičí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 582x (84.82 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

Předchozí článek
LINQ to XML v C# .NET
Všechny články v sekci
Soubory v C# .NET
Přeskočit článek
(nedoporučujeme)
Řešené úlohy k 6.-10. lekci práce se soubory v C# .NET
Článek pro vás napsal Jan Vargovský
Avatar
Uživatelské hodnocení:
66 hlasů
H̴̢̡̛̫̙̖̦͍̥̺̳̪͖̺̫̲͇̗̹̠̥͈̭͔̻̗͚̭̥̝͐̋͒̆̾̅͒̈̐̀̒̔̇̈̔̆̎̔͐̊͆̆̐̊̈͆̂̐̓̓͛̌̈́̈́̅̅̔̚̕̚͠͝͝͝͝ì̸͇͖̹̯̤͇͍̹̥̅͗͆̄̌͆͑̓̈́̓̊̈́͋̈́͛͊͛͂̇͋͒̿̃͐͌̐̚͝͝͝͝͝͝.̶̧̡̧̧̖̫̯̞͖̯̩̠̭̩͇͔̤̱̜̠̠̙͉͉̼̱͓̣͍̱͎͕̦͓̫̗̮̦͍͚̗͕̥̳͚̬̯̞̟͇̻̺̙͙̜͖̰̊͒̌̌̚͜͜͝
Aktivity