Práca s vlastnými súbory v C # 2 - Ukladanie a načítanie zips
V minulom tutoriále o vlastnom formátu súborov sme si predstavili možnosti archívov zips a založili projekt s formulárom pre zadanie zamestnancov. V tomto diele sa naučíme pracovať so zložkou ZIP, ukladať a otvárať súbory vlastného typu.
Načítanie hodnôt do objektu zamestnanca
Teraz musíme do zamestnanca hodnoty z formulára načítať. Presuňme sa späť ku kódu formulára. Všetkým textovým poliam pridajte rovnakú obsluhu udalosti pre KeyUp. V tejto obsluhe dosaďte do zamestnanca hodnoty z textových polí. Metóda zároveň aktualizuje záhlavie okna. KeyUp preto, aby sa udalosť nevyvolávala, keď dosadzujeme do políčka hodnoty z kódu. To bude jedna z ďalších metód.
private void SynchronizacePoli(object sender, KeyEventArgs e) { zamestnanec.Jmeno = txtJmeno.Text; zamestnanec.Prijmeni = txtPrijmeni.Text; zamestnanec.Email = txtEmail.Text; zamestnanec.Telefon = txtTelefon.Text; this.Text = txtJmeno.Text + " " + txtPrijmeni.Text; }
Jediný prvok dtbNarozeni bude využívať udalosti ValueChanged. V obsluhu zamestnanci dosadí svoju hodnotu.
private void dtpNarozeni_ValueChanged(object sender, EventArgs e) { zamestnanec.DatumNarozeni = dtpNarozeni.Value; }
Teraz budeme potrebovať opak a to nastaviť hodnoty zo zamestnanca do formulára. Toho využijeme keď otvoríme súbor so zamestnancom a budeme ho chcieť načítať. Preto si napíšeme metódu AktualizujFormularovaData. Metóda dosadí do všetkých políčok hodnoty zo zamestnancov. Metóda opäť aktualizuje aj záhlavie okna.
private void AktualizujFormularovaData() { txtJmeno.Text = zamestnanec.Jmeno; txtPrijmeni.Text = zamestnanec.Prijmeni; txtEmail.Text = zamestnanec.Email; txtTelefon.Text = zamestnanec.Telefon; dtpNarozeni.Value = zamestnanec.DatumNarozeni; pcbFoto.Image = zamestnanec.Foto; this.Text = txtJmeno.Text + " " + txtPrijmeni.Text; }
Ukladanie súboru
Zamestnanec bude mať metódu Uloz, ktorá bude prijímať jediný parameter a to cestu k súboru * .zamestnanec. Metóda bude ukladať zamestnanca do zazipované zložky so súbormi foto.jpg a info.xml. Pre info.xml budeme potrebovať metódu, ktorá vygeneruje xml a zapíše xml do archívu. V metóde budeme dosť často pracovať s dátovými prúdmi.
Najprv si vytvoríme dočasný priečinok, kam budeme dáta ukladať. Ukladať dáta priamo do archívu by totiž bolo zbytočne problémové. Využijeme metódy Path.Combine, ktorú skombinujeme s AppData, zložkou pre našu aplikáciu a náhodným názvom. Túto zložku vytvoríme.
string cestaTemp = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"zamestnanci\", Path.GetRandomFileName()); Directory.CreateDirectory(cestaTemp);
Pomocou konštrukcia Using vytvoríme dátový prúd pre súbor info.xml v našej dočasnej zložke.
using (FileStream fs = new FileStream(Path.Combine(cestaTemp, "info.xml"), FileMode.Create)) { UlozInfo(fs); }
Tento prúd odovzdáme privátne metóde UlozInfo, ktorá do prúdu zapíše XML.
private void UlozInfo(Stream proud)
Je na vás či XML zapíšete pomocou SAX, DOM alebo budete serializovať. V tomto článku to ani nebudem popisovať detailne. Môj kód exportu vyzerá nasledovne.
XmlDocument doc = new XmlDocument(); XmlElement zamestnanci = doc.CreateElement("Zamestnanci"); XmlElement zamestnanec = doc.CreateElement("Zamestnanec"); zamestnanci.AppendChild(zamestnanec); XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", null); doc.AppendChild(dec); doc.AppendChild(zamestnanci); XmlElement Jmeno = doc.CreateElement("Jmeno"); Jmeno.AppendChild(doc.CreateTextNode(this.Jmeno)); XmlElement Prijmeni = doc.CreateElement("Prijmeni"); Prijmeni.AppendChild(doc.CreateTextNode(this.Prijmeni)); XmlElement Email = doc.CreateElement("Email"); Email.AppendChild(doc.CreateTextNode(this.Email)); XmlElement Telefon = doc.CreateElement("Telefon"); Telefon.AppendChild(doc.CreateTextNode(this.Telefon)); XmlElement DatumNarozeni = doc.CreateElement("DatumNarozeni"); DatumNarozeni.AppendChild(doc.CreateTextNode(this.DatumNarozeni.ToShortDateString())); zamestnanec.AppendChild(Jmeno); zamestnanec.AppendChild(Prijmeni); zamestnanec.AppendChild(Email); zamestnanec.AppendChild(Telefon); zamestnanec.AppendChild(DatumNarozeni); doc.Save(proud);
Teraz sa vráťme k metóde Uloz. Vytvoríme ďalší stream, tentoraz pre foto.jpg. Obrázok uložíme jeho metódou Save, ktorá prijíma dátový prúd a výstupný formát. Vďaka výstupného formátu sme schopní obrázok previesť. Hoci treba užívateľ vloží obrázok ako BMP, vždy bude v archíve uložený ako JPG.
using (FileStream fs = new FileStream(Path.Combine(cestaTemp, "foto.jpg"), FileMode.Create)) { this.Foto.Save(fs, ImageFormat.Jpeg); }
Zipovanie zložky v C# .NET
.NET Framework 4.5 a vyššie obsahuje triedy pre prácu so zipováním súborov. Sú v mennom priestore System.IO.Compression. Aby ste však tieto menné priestory videli, musíte si pridať k projektu 2 referencie. V Solution Exploreri kliknite pravým tlačidlom na References> Add New Referencie.
Do vyhľadávacieho políčka napíšte System.IO a označte referencie System.IO.Compression a System.IO.Compression.FileSystem.
Dialóg potvrďte. Do Using si pridajte odkazy na tieto knižnice.
Trieda ZipFile má statickú metódu CreateFromDirectory, ktorá prijíma dva parametre. Prvý parameter je cesta k priečinku, ktorá má byť zazipované a druhý je výsledný súbor. Tento súbor nemusí mať nutne príponu zips a toho využijeme. Viacmenej však iba metóde dosadíme cesty.
ZipFile.CreateFromDirectory(cestaTemp, soubor);
Vráťme sa do formulára. Vytvorte udalosť Click na objekte btnUlozit. Opäť budeme vytvárať dialóg. Pretože filter pre príponu zamestnancov použijeme 2 × (otváranie a ukladanie), dáme ju triede Zamestnanec ako statický člen.
public static string filter = "Soubor zaměstnance (*.zamestnanec)|*.zamestnanec";
Dialógu dosadíme predvolený názov súboru, ktorý bude vychádzať z mena a priezviska zamestnanca. Dialóg otvoríme. Ak vráti OK, zamestnancov uložíme.
private void btnUlozit_Click(object sender, EventArgs e) { SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = Zamestnanec.filter; dialog.FileName = zamestnanec.Jmeno + " " + zamestnanec.Prijmeni; if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { zamestnanec.Uloz(dialog.FileName); } }
Aplikáciu si spustite. Vyberte nejakú fotku, vyplňte textové polia a nejaké dátum. Skúste zamestnanca uložiť. Skúste zmeniť jeho príponu na zips a pozrite sa dovnútra. Bude tam fotka a súbor info.xml.
Otvárania súborov v programe
Otvárania súboru budeme riešiť v druhom preťaženom konstruktoru. Do konstruktoru nám v parametri bude odovzdaná cesta k súboru so zamestnancom. Z tohto súboru potrebuje získať dátový prúd, ten odovzdáme v konštrukcii Using konstruktoru triedy ZipArchive.
public Zamestnanec(string soubor) { using (FileStream fs = new FileStream(soubor, FileMode.Open)) { using (ZipArchive zip = new ZipArchive(fs)) { } } }
ZipArchive má metódu GetEntry, ktorá vráti ZipArchiveEntry. Ten obsahuje súbor uložený v archíve. ZipArchiveEntry má potom metódu Open, ktorá vracia dátový prúd k súboru. Info.xml budeme načítavať v metóde NactiInfo, ktoré opäť odovzdáme dátový prúd a tá spracuje XML.
ZipArchiveEntry info = zip.GetEntry("info.xml");
NactiInfo(info.Open());
NactiInfo môžete zase napísať viacerými spôsobmi, ja som použil DOM. Môj kód vyzerá nasledovne.
private void NactiInfo(Stream proud) { XmlDocument doc = new XmlDocument(); using (XmlReader r = XmlReader.Create(proud)) { doc.Load(r); this.Jmeno = doc.GetElementsByTagName("Jmeno")[0].FirstChild.Value; this.Prijmeni = doc.GetElementsByTagName("Prijmeni")[0].FirstChild.Value; this.Email = doc.GetElementsByTagName("Email")[0].FirstChild.Value; this.Telefon = doc.GetElementsByTagName("Telefon")[0].FirstChild.Value; this.DatumNarozeni = DateTime.Parse(doc.GetElementsByTagName("DatumNarozeni")[0].FirstChild.Value); } }
Fotku načítame podobne, z dátového prúdu obrázok dostaneme pomocou statickej metódy Image.FromStream.
ZipArchiveEntry foto = zip.GetEntry("foto.jpg"); this.Foto = Image.FromStream(foto.Open());
Vráťme sa k formuláru a vytvorte obsluhu udalosti Click pre tlačidlo otvoriť. Opäť vytvoríme dialóg a opäť mu načítame filter. Otvoríme ho a porovnáme návratovú hodnotu s OK. Ak používateľ súbor vyberie, vytvoríme nového zamestnanca a v konstruktoru mu odovzdáme cestu k súboru. Nakoniec aktualizujeme dáta na formulári, aby sa zmeny zo zamestnanca prejavili aj na formulári. Celá metóda by mohla vyzerať nasledovne.
private void btnNacist_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = Zamestnanec.filter ; if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { zamestnanec = new Zamestnanec(dialog.FileName); AktualizujFormularovaData(); } }
Teraz je aplikácia hotová, môžete vyskúšať.
Aplikáciu poriadne vyskúšajte, nabudúce sa pozrieme na možné vylepšenia. Ošetríme chyby a vyšperkuje súbory v prieskumníkovi Windows. V kóde pod článkom máte na testovanie priloženého i plne validného zamestnanca Jána Nováka.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 259x (67.65 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#