6. diel - Programujeme pre Windows 8 - Práca so súbormi
V minulej lekcii, Programujeme pre Windows 8 - Zachovanie stavu aplikácie , sme si ukázali akým spôsobom obsluhovať základné Life-Cycle aplikácie. V dnešnom tutoriále si ukážeme niekoľko spôsobov ako čítať a zapisovať dáta do súborov.
Každá aplikácia môže zasahovať iba do vopred určených zložiek. Nemôžeme si vynútiť uloženie nejakého súboru mimo vyhradené zložky bez vedomia užívateľa. Ak budeme chcieť uložiť súbor mimo tieto špeciálne zložky, musíme využiť tzv. Pickery (viď. Nižšie).
Zložky
Ešte raz zložky, kam môžeme zasahovať bez vedomia užívateľa. Zložky sú tiež označované ako Isolated Storage, teda Izolované úložiska.
- Local Folder - zložka pre súbory (.txt, .xml, obrazové súbory, ...)
- Roaming Folder - to isté ako Local s tým rozdielom, že táto zložka sa automaticky synchronizuje cez SkyDrive ak ho má používateľ aktívny
- Temp Folder - Komponent dočasné súbory. Súbory po znovu otvorení aplikácie zmizne.
- Local Settings - Miesto pre ukladanie rôzneho nastavenia. Je to dátový kontajner. K hodnotám pristupujeme cez Kľúče. Teda Kľúč - Hodnota
- Roaming Settings - To isté ako Local Settings a opäť synchronizácii cez SkyDrive
Nasledujúce zložky poznáme aj z predošlých systémov a vo WinRT sú označované ako KnownFolders
- Documents - Zložka určená pre dokumenty
- Pictures - Komponent obrázky
- Videos - Komponent video
- Music - Zložka pre audio
Pozn. Koho by zaujímalo kde sa Local / Roaming zložky nachádzajú tak je to tu: C: \ Users \ Menoužívateľa \ Local \ Packages \ APLIKÁCIE. V packages majú aplikácie meno podľa kľúča. Musíte holt hľadať
Uloženie
Poďme si teda niečo uložiť. Uložíme iba .txt súbor vo formáte CSV. Budeme mať databázu používateľov (pozri tento článok http://www.itnetwork.cz/...-souboru-csv od sdraco). Nebudem tu riešiť žiadny návrh aplikácie a objektov. Predpokladám, že máme teda List <Uzivatel> uzivatele. Každý má meno, vek a dátum registrácie. Metóda pre uloženie môže vyzerať nasledovne
public async Task<bool> UlozUzivatele() { //zíká složku Local Folder StorageFolder folder = ApplicationData.Current.LocalFolder; //vytovří nový soubor asynchronně StorageFile file = await folder.CreateFileAsync("uzivatele.txt"); try { // načte stream Stream stream = await file.OpenStreamForWriteAsync(); //založí StreamWriter ze stream /* * Můžeme místo StreamWriter použít i FileIO a metodu jako WriteTextAsync * */ using (StreamWriter writer = new StreamWriter(stream)) { //Zapíšeme uživatele foreach (Uzivatel u in uzivatele) { await writer.WriteLineAsync(string.Format("{0},{1},{2}", u.Jmeno, u.Vek, u.Registrovan.ToString("d.M.y"))); } } await stream.FlushAsync(); return true; } catch { return false; } }
Metóda je celkom prostá. Získame zložku, založíme súbor. Zo súboru vytvoríme stream a zapíšeme text. Stream potom uzavrieme. Určite Vás ale zaráža jedna vec. Kľúčové slová ako async a Await už sme raz použili a opäť vás sklamem. Dnes si to ešte nevysvetlíte. Berte to ako kúzelné slovíčko, ktoré nám zaistí asynchrónne beh metód. Celú metódu kvôli používaniu asynchroních metód StreamWriter, Streamu apod musíme označiť ako async! Tým hovoríme, že zakladáme nové vlákno a kdekoľvek je Await, hlavné vlákno s UI beží (reaguje) stále ďalej a v pozadí sa dejú ďalšie výpočty.
Predovšetkým v prostredí Windows 8 aplikácií sa snažte o asynchrónne prístup. Aplikácia neprejde ani certifikáciou ak vám hlavné vlákno s UI zamrzne!
Ak async metóda potrebuje niečo vracať, musí vracať objekt typu Task <T> alebo void.
Ak chceme RoamingFolder, jednoducho načítame Roaming Folder a postup je rovnaký. Načítanie myslím nie je potreba ukazovať. Namiesto StreamWriter by sme použili StreamReader a zo zložky by sme načítali súbor cez GetFileAsync (). Samozrejme miesto StreamWriter / Readeru je možnosť použiť statickú triedu FileIO. Záleží na situáciu a potreby uloženia.
Xml Serializácie
Formát CSV sa hodí naozaj na pár skromných riadkov dát. Oveľa lepšie a prehľadnejšie je XML formát. Máme tu stále možnosť použiť XmlReader / Writer. My si ukážeme jednoduchší a rýchlejší spôsob, ak chceme načítať všetko a vieme čo presne načítame.
Hlavné triedou, ktorá bude potrebné, je XmlSerializer. Trieda ktorá predstavuje dáta musia mať vždy konštruktor bez parametrov a samozrejme pokojne ďalšie s parametrami. Skromná trieda:
public class User { public string Name{get;set;} public int Age{get;set;} private User() {} public User(string name,int age) { this.Name = name; this.Age = age; } }
dáta:
List<User> users = new List<User>(){ new User("Pepa",15), new User("Vašek",25), new User("Jarmila",15) };
A kód pre serializáciu a uloženie
public async Task<bool> Uloz() { try { StringWriter w = new StringWriter(); //Načteme složku StorageFolder folder = ApplicationData.Current.RoamingFolder; //Vytvoříme soubor a v případě existence přemažeme StorageFile file = await folder.CreateFileAsync("notes.xml", CreationCollisionOption.ReplaceExisting); //Založíme Serializer typu List<User> XmlSerializer srl = new XmlSerializer(typeof(List<User>)); //serializujeme srl.Serialize(w, users); //zapíšeme přes FileIO await FileIO.WriteTextAsync(file, w.ToString()); // zavřeme StreamWriter await w.FlushAsync(); return true; } catch { return false; } }
Opäť myslím, že kód hovorí za všetko
Podobne bude načítanie:
public async Task<bool> Nacti() { try { // načteme složku StorageFolder folder = ApplicationData.Current.RoamingFolder; //načteme soubor StorageFile file = await folder.GetFileAsync("users.xml"); //založíme Serializer XmlSerializer srl = new XmlSerializer(typeof(List<User>)); // přeteme text ze souboru (ještě stále XML formát) string text = await FileIO.ReadTextAsync(file); // založíme XmlReader XmlReader r = XmlReader.Create(new StringReader(text)); //Deserializujeme a přetypujeme users = (List<User>)srl.Deserialize(r); return true; } catch { return false; } }
Vidíme, že práca s XML je veľmi jednoduchá ak nepotrebujeme vytiahnuť určitej časti XML
Pickery
Picker je (s trochou nepresnosti) komponenta, ktorá umožňuje užívateľovi uložiť / načítať súbor alebo otvoriť zložku pre čítanie. Je to tiež jediný správny postup ako uložiť dáta mimo určenej zložky. Užívateľ vždy musí vedieť čo sa mu deje na zariadení (PC, tablet, ...).
Picker máme teda 3 typy
- FileOpenPicker - načíta jeden alebo viac súborov
- FileSavePicker - uloží jeden alebo viac súborov do nastavenej cesty
- FolderPicker - umožní otvoriť zložku vnútri aplikácie
U FileOpenPicker a FolderPicker nájdeme jednu dôležitú vlastnosť a tým je FileTypeFilter. Ide o kolekciu List <string> a udáva aký typ súborov môžeme otvoriť / uložiť. Ak chceme všetky typy pridáme do kolekcie hviezdičku () alebo určíme presne typy súborov a to uvedením prípony: .txt, .xtml, .png, ... Podobne u * FileSavePicker nájdeme vlastnosť FileTypeChoices ktorá udáva čo môžeme zvoliť.
Ukážka Picker, ktorý načíta zvolený súbor.
FileOpenPicker picker = new FileOpenPicker(); picker.FileTypeFilter.Add(".txt"); StorageFile file = await picker.PickSingleFileAsync(); IList<string> result = await FileIO.ReadLinesAsync(file, UnicodeEncoding.Utf8);
Pickery dokážu uložiť aj viac súborov naraz. Určite si pozrite ďalšie nastavenia Picker. Možno je rôzne stylovať
Settings
LocalSettings alebo RoamingSettings je špeciálny kontajner, kde môžeme ľahko uchovávať hodnoty podľa kľúča. Je to akýsi trvalý Dictionary. Myslím, že nie je tu čo viac uvádzať.
// uložení ApplicationData.Current.LocalSettings.Values["name"] = "Zirko"; //načtení string name = ApplicationData.Current.LocalSettings.Values["name"].ToString();
KnownFolders
Načítanie a ukladanie do KnownFolders je rovnako jednoduché ako ostatné. napríklad Videos
StorageFolder videosFolder = KnownFolders.VideosLibrary;
Capabilities
S KnownFolders as mnohými ďalšími vecami (v budúcnosti si povieme viac) súvisí Package.appxmanifest. V prvom diele sme si o tomto súbore niečo málo povedali. Pokiaľ využívate KnownFolders, musíte zaškrtnúť tú library, ktorú používate a pridať deklarácie. Avšak už prekračujeme dnešnej náplň článku. Detailnejšie si to popíšeme inokedy.
Dnešný článok bol veľmi teoretický, v budúcej lekcii, Programujeme pre Windows 8 - Vlastné štýly v XAML sa vrhneme na niečo zaujímavejšie