SOUBORY, VSTUPY A VÝSTUPY POKRAČOVÁNÍ



Podobné dokumenty
SOUBORY, VSTUPY A VÝSTUPY POKRAČOVÁNÍ

PŘETĚŽOVÁNÍ OPERÁTORŮ

PREPROCESOR POKRAČOVÁNÍ

TŘÍDY POKRAČOVÁNÍ. Události pokračování. Příklad. public delegate void ZmenaSouradnicEventHandler (object sender, EventArgs e);

Jazyk C# (seminář 5)

Generické programování

SOUBORY, VSTUPY A VÝSTUPY

Pokud neuvedeme override, vznikne v synu nová (nevirtuální) metoda (a pochopitelně se nezavolá, jak bychom

Principy objektově orientovaného programování

Úvod Třídy Rozhraní Pole Konec. Programování v C# Hodnotové datové typy, řídící struktury. Petr Vaněček 1 / 39

Zápis programu v jazyce C#

Druhy souborů. textové. binární. nestrukturované txt strukturované - ini, xml, csv. veřejné bmp, jpg, wav proprietární docx, cdr, psd

Seminář Java II p.1/43

Teoretické minimum z PJV

Soubor jako posloupnost bytů

Programování v Javě I. Únor 2009

Úvod do programovacích jazyků (Java)

Ošetřování chyb v programech

8. přednáška: Soubory a proudy

Textové soubory. alg9 1

Programování v Javě I. Leden 2008

Základy objektové orientace I. Únor 2010

Výčtový typ strana 67

Fakulta elektrotechniky a informatiky Univerzita Pardubice 2014/2015. poslední přednáška a materiál k samostudiu

1. Téma 12 - Textové soubory a výjimky

IRAE 07/08 Přednáška č. 1

PROMĚNNÉ, KONSTANTY A DATOVÉ TYPY TEORIE DATUM VYTVOŘENÍ: KLÍČOVÁ AKTIVITA: 02 PROGRAMOVÁNÍ 2. ROČNÍK (PRG2) HODINOVÁ DOTACE: 1

Základy jazyka C# Obsah přednášky. Architektura.NET Historie Vlastnosti jazyka C# Datové typy Příkazy Prostory jmen Třídy, rozhraní

IAJCE Přednáška č. 8. double tprumer = (t1 + t2 + t3 + t4 + t5 + t6 + t7) / 7; Console.Write("\nPrumerna teplota je {0}", tprumer);

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Univerzita Palackého v Olomouci Radek Janoštík (Univerzita Palackého v Olomouci) Základy programování 4 - C# 19.2.

7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd

7. Datové typy v Javě

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

Úvod Informace o prostředí Práce se soubory Regulární výrazy Konec. Programování v C# Soubory a regulární výrazy. Petr Vaněček 1 / 27

Kolekce, cyklus foreach

Java a XML. 10/26/09 1/7 Java a XML

2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus pro vyhledání položky v binárním stromu.

Programování v C++ 3, 3. cvičení

přetížení operátorů (o)

Více o konstruktorech a destruktorech

Programování v C++ 1, 5. cvičení

Dynamicky vázané metody. Pozdní vazba, virtuální metody

Znaky. IAJCE Přednáška č. 10. každému znaku je nutné přiřadit nějaké číslo (nezáporné přímé mapování znak <->

Java Výjimky Java, zimní semestr

Jazyk C# (seminář 6)

IRAE 07/08 Přednáška č. 2. atr1 atr2. atr1 atr2 -33

Class loader. každá třída (java.lang.class) obsahuje referenci na svůj class loader. Implementace class loaderu

UJO Framework. revoluční architektura beans. verze

Programování v C++ 2, 4. cvičení

Osnova přednášky. Programové prostředky řízení Úvod do C# II. Přístup ke členům. Členy (Members)

Bridge. Známý jako. Účel. Použitelnost. Handle/Body

Dědičnost (inheritance)

Paměť počítače. alg2 1

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

typová konverze typová inference

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Programování v C++ 1, 6. cvičení

Jazyk C++ 1. Blok 3 Objektové typy jazyka C++ Třída. Studijní cíl. Doba nutná k nastudování. Průvodce studiem

Středoškolská technika 2017 PROGRAM NA GENEROVÁNÍ PRVOČÍSEL

Z. Kotala, P. Toman: Java ( Obsah )

C# - I/O, streamy, práce se soubory

Polymorfismus. Časová náročnost lekce: 3 hodiny Datum ukončení a splnění lekce: 30.března

Abstraktní datové typy: zásobník

III/2 Inovace a zkvalitnění výuky prostřednictvím ICT

Úvod Přetěžování Generika Kolekce Konec. Programování v C# Další jazykové konstrukce. Petr Vaněček 1 / 31

Seznamy a iterátory. Kolekce obecně. Rozhraní kolekce. Procházení kolekcí

Algoritmizace a programování. Terminálový vstup a výstup

Předmluva k aktuálnímu vydání Úvod k prvnímu vydání z roku Typografické a syntaktické konvence... 20

PB161 Programování v jazyce C++ Přednáška 7

4. ZÁKLADNÍ POJMY Z OBJEKTOVĚ ORIENTOVANÉHO PROGRAMOVÁNÍ

Objekty v PHP 5.x. This is an object-oriented system. If we change anything, the users object.

PB161 Programování v jazyce C++ Přednáška 7

ADT/ADS = abstraktní datové typy / struktury

1. Programování proti rozhraní

Remote Method Invocation RMI

Abstraktní třída a rozhraní

URČITÝM ZPŮSOBEM PODOBNÉ

NPRG031 Programování II 1 / :47:55

FORMÁTOVÁNÍ POKRAČOVÁNÍ

Chování konstruktorů a destruktorů při dědění

PB161 Základy OOP. Tomáš Brukner

Úvod do programování - Java. Cvičení č.4

8 Třídy, objekty, metody, předávání argumentů metod

Jazyk C# (seminář 3)

Abstraktní třídy, polymorfní struktury

Třídy. Instance. Pokud tento program spustíme, vypíše následující. car1 má barvu Red. car2 má barvu Red. car1 má barvu Blue.

Dědění, polymorfismus

NMIN201 Objektově orientované programování 2016/17 1 / :03:29

Obsah přednášky 9. Skrývání informací. Skrývání informací. Zapouzdření. Skrývání informací. Základy programování (IZAPR, IZKPR) Přednáška 9

Pokročilé programování v jazyce C pro chemiky (C3220) Operátory new a delete, virtuální metody

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

Konstruktory a destruktory

Počítačové laboratoře bez tajemství aneb naučme se učit algoritmizaci a programování s využitím robotů CZ.1.07/1.3.12/

1. Dědičnost a polymorfismus

OOPR_05. Případové studie

Jazyk C# a platforma.net

Transkript:

SOUBORY, VSTUPY A VÝSTUPY POKRAČOVÁNÍ Vstupy a výstupy pokračování Kódování textů Texty (řetězce nebo znaky) v jazyce C# jsou v paměti uloženy v kódování označovaném běžně Unicode (kódová stránka 1200). Texty vypisované na obrazovku konzolové aplikace se implicitně převádí do kódování Latin 2 (kódová stránka 852). Texty zapisované do datového proudu se implicitně převádí do kódování UTF-8 (kódová stránka 65001). Při čtení se provádí opačný převod. UTF je zkratka slov Unicode Transformation Format a určuje způsob zakódování Unicode kódů (znaků 16-ti bitových kódů) bez ztráty informací. Existují následující typy: UTF-7 zastaralý způsob kódování, UTF-8 převádí Unicode kód na posloupnost jednoho až čtyř bytů, UTF-16 převádí Unicode kód na posloupnost jednoho až dvou 16-bitových celých čísel, UTF-32 převádí Unicode kód na jedno 32-bitové celé číslo. Kódování UTF-16 a UTF-32 mají dva podtypy: little-endian byte order např. znak A '\u0041' je zapsán v UTF-16 ve tvaru 00 41, big-endian byte order např. znak A '\u0041' je zapsán v UTF-16 ve tvaru 41 00. Běžné označení Unicode kódování je kódování UTF-16 little-endian byte order. Jeden Unicode kód umožňuje uchovat 65 535 znaků. Tento počet nestačí pro uchování všech znaků jazyků světa. Např. čínský jazyk vyžaduje více než 80 000 znaků. Tyto a další znaky lze však také uchovat, a to jako dvojici znaků základní znak a doprovodný znak. Doprovodné znaky jsou definovány v rozsahu '\u0328' až '\u0345' (podle [2]). Např. znak o (malé o s ogonkem) lze zapsat jako dvojici znaků "\u006f\u0328". Typ kódování textů lze zadat v parametru konstruktoru datových proudů BinaryReader, BinaryWriter, StreamReader a StreamWriter. Parametr je typu System.Text.Encoding, což je abstraktní třída, která je předkem tříd, jež představují jednotlivá kódování. Většina potřebných kódování je k dispozici pomocí statických složek třídy Encoding: vlastnost Default poskytuje implicitní kódování kódové stránky ANSI nastavené v operačním systému. Pro česká Windows je to 1250. vlastnost Unicode poskytuje kódování UTF-16 little-endian byte order. vlastnost UTF8 poskytuje kódování UTF-8. vlastnost UTF32 poskytuje kódování UTF-32 little-endian byte order. metoda GetEncoding(int codepage) vrací kódování pro zadané číslo kódové stránky. Třída Console umožňuje změnit kódování nebo zjistit aktuální kódování pro čtení a výpis pomocí dvou statických vlastností InputEncoding a OutputEncoding. Příklad Program uloží zadaný text do textového souboru v implicitním kódování ANSI, což v českých Windows bude kódová stránka 1250. 1

class Program static void UlozText(string jmeno, string text, Encoding encoding) using (StreamWriter sw = new StreamWriter(File.Create(jmeno), encoding)) sw.writeline(text); static void Main(string[] args) string text = "Nějaký český text"; UlozText("data.txt", text, Encoding.Default); Paměťové datové proudy Paměťové datové proudy jsou v jazyce C# orientovány na pole bytů, a ne na řetězce znaků jako je tomu v C++. Paměťový datový proud reprezentuje třída MemoryStream, která je potomkem třídy Stream. Obsahuje mj. tyto konstruktory: MemoryStream() vytvoří prázdný proud. MemoryStream(byte[] buffer) vytvoří proud svázaný s externím polem bytů buffer. Pole bytů nelze později zvětšit. MemoryStream(int capacity) vytvoří proud s vnitřním polem bytů velikosti capacity. Pole bytů lze později zvětšit. Pro čtení a zápis z/do paměťového proudu lze využít metody třídy Stream, ale zpravidla se využívají třídy BinaryReader, BinaryWriter, StreamReader a StreamWriter. Třída MemoryStream mj. obsahuje metodu byte[] ToArray(), která vrací kopii vnitřního pole bytů paměťového proudu. Příklad Program provádí konverzi řetězce znaků z jednoho kódování do jiného. Text určený ke konverzi se zapíše do pole bytů pomocí paměťového datového proudu v zadaném kódování. Pole bytů se převede z jednoho kódování na jiné pomocí statické metody Convert třídy Encoding: byte[] Convert(Encoding srcencoding, Encoding dstencoding, byte[] bytes) Metoda Convert převede pole bytů bytes z kódování srcencoding na kódování dstencoding a vrací převedené pole bytů. Převod pole bytů na řetězec provádí statická metoda GetString příslušné třídy kódování. V příkladu je to třída, kterou poskytuje vlastnost Encoding.Unicode. 2

class Program static void Main(string[] args) string text = "Nějaký český text"; MemoryStream ms = new MemoryStream(); using (StreamWriter sw = new StreamWriter(ms, Encoding.Default)) sw.write(text); byte[] buffer = ms.toarray(); buffer = Encoding.Convert(Encoding.Default, Encoding.Unicode, buffer); string text2 = Encoding.Unicode.GetString(buffer); Console.WriteLine(text2); Pro převod řetězce znaků na pole bytů kódové stránky odpovídající danému potomkovi třídy Encoding slouží virtuální metoda GetBytes třídy Encoding: virtual byte[] GetBytes(string s) Např. převod řetězce znaků s na pole bytů kódové stránky 1250 lze provést příkazem byte[] b = Encoding.Default.GetBytes(s); Příklad Příklad demonstruje uložení pole tříd Osoba do binárního souboru a jeho načtení. Záznam osoby v souboru má pevnou délku, což umožňuje případné načtení jen konkrétního záznamu v souboru. Při ukládání údajů osoby se vytvoří pole bytů odpovídající délce záznamu osoby, které se spojí s paměťovým proudem. Do paměťového proudu se binárně uloží údaje osoby. Potom se pole bytů uloží do binárního souboru. Při čtení údajů osoby se z binárního souboru načte pole bytů odpovídající délce záznamu osoby. Toto pole se spojí se paměťovým proudem, ze kterého se binárně načtou údaje osoby. class Osoba public const int Delka = 100; public int cislo; public string jmeno; public Osoba() public Osoba(int cislo, string jmeno) this.cislo = cislo; this.jmeno = jmeno; public void NactiPevnaDelka(BinaryReader br) byte[] buffer = br.readbytes(delka); MemoryStream ms = new MemoryStream(buffer); using (BinaryReader br2 = new BinaryReader(ms)) cislo = br2.readint32(); jmeno = br2.readstring(); 3

public void UlozPevnaDelka(BinaryWriter bw) byte[] buffer = new byte[delka]; MemoryStream ms = new MemoryStream(buffer); using (BinaryWriter bw2 = new BinaryWriter(ms)) bw2.write(cislo); bw2.write(jmeno); bw.write(buffer); class Program static void UlozPevnaDelka(string jmeno, Osoba[] osoby) using (BinaryWriter bw = new BinaryWriter(File.Create(jmeno))) foreach (Osoba osoba in osoby) osoba.ulozpevnadelka(bw); static void NactiPevnaDelka(string jmeno, out Osoba[] osoby) FileStream fs = File.OpenRead(jmeno); int pocet = (int)(fs.length / Osoba.Delka); osoby = new Osoba[pocet]; using (BinaryReader br = new BinaryReader(fs)) for (int i = 0; i < pocet; i++) osoby[i] = new Osoba(); osoby[i].nactipevnadelka(br); static void Main(string[] args) Osoba[] osoby = new Osoba[3] new Osoba(10, "Čejka"), new Osoba(20, "Dvořák"), new Osoba(30, "Mojžíš") ; try UlozPevnaDelka("data.bin", osoby); NactiPevnaDelka("data.bin", out osoby); foreach (Osoba osoba in osoby) Console.WriteLine("0 1", osoba.cislo, osoba.jmeno); catch (Exception e) Console.WriteLine("Chyba: " + e.message); Console.ReadKey(); Výstup programu bude následující: 10 Čejka 20 Dvořák 30 Mojžíš 4

Serializace objektů Serializace představuje mechanizmus, umožňující uložit do datového proudu jakýkoli objekt. Objekt může obsahovat odkazy na jiné objekty, které se mohou odkazovat zase na další objekty atd. Spolu s ukládaným objektem se uloží i objekty, na které se objekt přímo nebo nepřímo odkazuje a informace o jejich vzájemných vztazích. Ukládá se tzv. objektový graf. Deserializace reprezentuje opačný proces než je serializace, tj. z datového proudu načte a vytvoří objekt včetně objektů, na které se přímo nebo nepřímo odkazuje. Serializaci objektů lze provést v následujících formátech: binární, SOAP (Simple Object Access Protocol) protokol založený na XML určený pro výměnu informací na webu, XML. Serializace v prvních dvou formátech se liší od XML serializace. Serializace v binárním nebo SOAP formátu Ukládané objekty musí splňovat následující požadavky: Třída (struktura), jejíž instance se má serializovat, musí být deklarována s atributem Serializable. Datové složky, které se nemají serializovat, se deklarují s atributem Nonserialized. Při načtení objektu z datového proudu se provede jejich inicializace v závislosti na jejich typu: jsou-li hodnotového typu, volá se pro ně implicitní konstruktor, jsou-li referenčního typu, mají hodnotu null. Datové složky, které se mají serializovat, musí být typu, který je deklarován s atributem Serializable, jinak při serializaci vznikne výjimka typu System.Runtime.Serialization.SerializationException. To se týká i datových složek objektu, na který se datová složka této třídy přímo nebo nepřímo odkazuje. Datové složky se serializují bez ohledu na jejich přístupová práva. Vlastnosti se neserializují. S atributem Serializable jsou deklarovány všechny základní datové typy, typ string i třídy kolekcí Array, ArrayList aj. Pro serializaci slouží následující třídy: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter serializace v binárním formátu, System.Runtime.Serialization.Formatters.Soap.SoapFormatter serializace ve formátu SOAP. Třída je součástí sestavení System.Runtime.Serialization. Formatters.Soap, které se v prostředí Visual Studio musí přidat do části References daného projektu. Běžně se používá konstruktor bez parametrů. Z metod se používají následující dvě: void Serialize(Stream serializationstream, object graph) zapíše objekt graph do datového proudu serializationstream. object Deserialize(Stream serializationstream) vrací objekt, který načte z datového proudu serializationstream. Obě třídy formátovačů implementují rozhraní IFormatter které obsahuje metody Serialize a Deserialize. Pokud tedy chceme provádět serializaci nějakého objektu nezávislého na formátu, lze pracovat s tímto rozhraním. 5

Do jednoho datového proudu lze serializovat i více objektů samostatným voláním metod Serialize a později je deserializovat metodami Deserialize ve stejném pořadí, v jakém byly serializovány. Pokud některá složka objektu, která se má serializovat, se metodou Deserialize nenačte, chování závisí na zvoleném formátovači: Pro binární formát výjimka nevznikne a taková složka se inicializuje stejnou hodnotou jako složka, která se nemá serializovat. Pro formát SOAP se vyvolá výjimka typu SerializationException. Pokud je však složka deklarována s atributem OptionalField, inicializuje se stejnou hodnotou jako složka, která se nemá serializovat a výjimka nevznikne. Příklad Příklad demonstruje serializaci třídy C, která obsahuje pole tříd B. Třída B obsahuje složky a, a2 typu struktury A a složku y typu int. Složka a2 se nebude serializovat. Jak třídy B a C, tak i struktura A musí být deklarovány s atributem Serializable, jinak při serializaci vznikne výjimka. [Serializable] struct A public int x; public A(int x) this.x = x; [Serializable] class B A a; [NonSerialized] A a2 = new A(-1); int y; public B(int x, int y) a = new A(x); this.y = y; public override string ToString() return "a.x = " + a.x + ", a2.x = " + a2.x + ", y = " + y; [Serializable] class C B[] b; public C(B[] b) this.b = b; public void Vypis() foreach (B x in b) Console.WriteLine(x.ToString()); 6

class Program static void Main(string[] args) C c = new C(new B[] new B(10, 20), new B(30, 40) ); BinaryFormatter bf = new BinaryFormatter(); // SoapFormatter bf = new SoapFormatter(); using (FileStream fs = new FileStream("data.bin", FileMode.Create)) bf.serialize(fs, c); c.vypis(); c = null; using (FileStream fs = new FileStream("data.bin", FileMode.Open)) c = (C)bf.Deserialize(fs); Console.WriteLine("Po načtení objektu ze souboru"); c.vypis(); Výstup programu bude následující: a.x = 10, a2.x = -1, y = 20 a.x = 30, a2.x = -1, y = 40 Po načtení objektu ze souboru a.x = 10, a2.x = 0, y = 20 a.x = 30, a2.x = 0, y = 40 Přizpůsobení serializace Proces serializace lze přizpůsobit např. za účelem určité transformace hodnot složek některé třídy, která je součástí objektového grafu. K tomuto účelu slouží rozhraní ISerializable, které musí třída, jež se má serializovat specifickým způsobem, implementovat. Třída musí i tak být deklarována s atributem Serializable. Rozhraní ISerializable je deklarováno následovně: public interface ISerializable void GetObjectData(SerializationInfo info, StreamingContext context); Metodu GetObjectData volá automaticky daný formátovač před uložením dané třídy do datového proudu. Třída, implementující uvedené rozhraní, musí naplnit parametr info kolekcí dvojic název/hodnota. Kde název zpravidla reprezentuje název datové složky, která se má serializovat, a hodnota její hodnotu. Třída SerializationInfo obsahuje pro účely serializace přetížené metody AddValue, které mají tvar: void AddValue(string name, typ value) kde typ reprezentuje jednotlivé základní datové typy. Pokud se má do kolekce přidat dílčí objekt objektového grafu (včetně objektů, na které odkazuje), na který se odkazuje příslušná datové složka třídy, lze volat metodu void AddValue(string name, object value) 7

Typ StreamingContext je struktura obsahující dvě vlastnosti: Context poskytuje objekt typu object, který může obsahovat libovolné dodatečné informace. State poskytuje příznaky, udávající o jaký typ serializace se jedná, např. serializace do souboru, mezi aplikačními doménami, mezi počítači apod. Obě tyto vlastnosti jsou inicializovány konstruktorem této třídy. Instanci této třídy lze předat konstruktoru příslušného formátovače. Třídy BinaryFormatter a SoapFormatter obsahují k tomuto účelu konstruktor se dvěma parametry: XxxFormatter(ISurrogateSelector selector, StreamingContext context) Parametr selector se používá při serializaci po síti pomocí technologie.net Remoting (podrobnosti viz nápověda). Pro jinou serializaci může být null. Kromě složek rozhraní ISerializable musí třída obsahovat chráněný konstruktor ve tvaru: protected NejakaTrida(SerializationInfo info, StreamingContext context) Je-li třída zapečetěná, může být konstruktor soukromý. Tento konstruktor volá daný formátovač po načtení hodnot dané třídy z datového proudu. Pro získání prvku z kolekce název/hodnota z třídy SerializationInfo se používají metody ve tvaru: typ GetTyp(string name) kde typ a Typ reprezentují jednotlivé základní datové typy. Pro deserializaci dílčího objektu objektového grafu lze volat metodu object GetValue(string name, Type type) Do parametru type se musí předat informace o skutečném typu dílčího objektu, který metoda vrací. 8