Živě.cz o počítačích a internetu

Umíme to s Delphi: 160. díl – streamy: shrnutí vlastností a metod

Václav Kadlec 23.8.2005

Dnešní článek podá přehledné shrnutí toho, čím jsme se zabývali v předchozích dílech seriálu. Podíváme se na přehled vlastností a metod tříd, které jsou určeny pro práci se streamy neboli datovými proudy. Informace, které jsme v předchozích článcích nalézali společně, živelně a empiricky, tak dostanou organizovanou podobu.

Dnešní článek uzavře téma, kterým se zabýváme v poslední době: datové proudy neboli streamy. Nejprve se stručně podíváme na připomenutí předchozích seriálových událostí, potom se podíváme na samotnou náplň dnešního článku.

Takže, co už o streamech víme? Drtivou většinu důležitých věcí: stream funguje jako jakési potrubí. Na jedné straně do něho cosi naléváme, na straně druhé jej kamsi připojíme. V důsledku toho tekutina jednoduše protéká z nádrže do jejího cílového umístění. Podobně funguje stream: na jedné straně jej kamsi připojíme (např. souborový stream do diskového souboru), na druhé straně do něho lijeme data. Po úvodním nakonfigurování streamu („připojení trubky“) data jednoduše protékají tak, jak chceme.

Jednou z hlavních výhod streamu, a zároveň jedním z hlavních důvodů, proč streamy vlastně používat, je skutečnost, že je lze velmi jednoduše zaměňovat jeden za druhý. Pokud se například jednoho dne rozhodneme, že data budeme chtít lít namísto do diskového souboru do síťového socketu, bude změna při použití streamů velmi, velmi jednoduchá. Právě v tomhle spočívá největší výhoda streamů – není obtížné rozhodnout se pro změnu používaného streamu a namísto diskového použít třeba paměťový a nebo síťový.

V předchozích částech seriálu jsme se podrobněji zabývali několika konkrétními druhy streamů a ukázali jsem si jejich praktické využití na demonstračních aplikacích. Jednalo se o následující streamy:

V dílu 154 jsme se pak zabývali úplnými streamovými fundamenty a podali jsme si základní informace o tom, co streamy jsou a jak se používají. V dílu s označením 158 jsme se zabývali dvěma důležitými otázkami souvisejícími se streamy: za prvé, jak jsou streamy podporovány komponentami knihovny VCL (zjistili jsme, že značně, především díky metodám LoadFromStream a SaveToStream, jejichž použití je stejně jednoduchoučké jako ranní nákup rohlíků) a za druhé, jak kopírovat jeden stream do druhého. Ani to není těžké, máme k dispozici metodu CopyFrom, která umožňuje stream naplnit daty z jiného streamu. Díl 159 se potom zaměřil na další dvě koncepce: na nastavování a využívání aktuální pozice ve streamu a také na velikost streamu.

Tolik k tomu, co se dělo dosud. A co se bude dít dnes? Dnes si společně načrtneme podkladový obrázek datových proudů: podíváme se na hierarchii tříd, které se streamy souvisí a vyjmenujeme nejdůležitější vlastnosti, události a metody streamů.

Hierarchie tříd - základem je TStream

Jaká je tedy třídní hierarchie týkající se datových proudů? Především – jak už jsme si řekli, základní třídou týkající se datových proudů je TStream. Z této třídy jsou pak oddědění konkrétní potomci, například třída pro práci se souborovými proudy, třída pro práci se síťovými proudy apod. Samotná třída TStream je pak přímým potomkem prapředka všech tříd v Delphi – třídy TObject.

K čemu je třída TStream dobrá? Samu o sobě ji použijeme jen velmi málokdy, v drtivé většině případů instancujeme (vytváříme objekty) přímo z konkrétních potomků TStream. Důvodem je, že každý potomek TStream v podstatě implementuje metody pro čtení/zápis ze/do konkrétního média, jako je například operační paměť nebo disk. V okamžiku, kdy se rozhodneme s kterým médiem chceme pracovat, vytvoříme objekt zvolené třídy (potomka TStream) a používáme proprietární (přímo k danému účelu určené) metody dané třídy.

Pokud už vás zajímá, k čemu by se dala použít samotná třída TStream, tak dokumentace Delphi doporučuje například podívat se čas od času na některé vlastnosti této třídy. Díky nim máme totiž přístup k některým informacím o streamu, například k jeho velikosti nebo k aktuální pozici, v němž se ve streamu zrovna nacházíme. Ano, velikost streamu a pozice ve streamu, kterými jsme se podrobně zabývali minule, jsou přímo atributy třídy TStream.

Také některé metody, o kterých jsme se bavili (a nebo také nebavili) a které jsme používali (a nebo také nepoužívali) v předchozích částech seriálu, jsou přímo obsaženy v TStream. Mám nyní na mysli například metody pro ukládání komponent, ale také obecně pro čtení ze streamu do bufferu nebo pro zápis bufferu do streamu. O streamování komponent jsme se prozatím nebavili, protože se jedná o širší problematiku, který by si žádala podstatně více prostoru a času. Tím neříkám, že se k ní v budoucnu nemůžeme vrátit.

Za okamžik si podáme přehlednou tabulku nejdůležitějších vlastností a metod třídy TStream. Ještě předtím však raději upozorněme, že TStream je abstraktní třída, která by neměla být instanciována. Jinak řečeno, neměli bychom vytvářet přímo objekty třídy TStream: potřebujeme-li pracovat se streamem, měli bychom zvolit konkrétního potomka TStream (např. TFileStream, TMemoryStream apod.) a vytvořit objekt z něho. Důvodem je především skutečnost, že TStream obsahuje abstraktní metody, které jsou definovány až v třídách potomků.

Následující přehled obsahuje potomky třídy TStream, tedy třídy určené pro realizaci konkrétních druhů datových proudů:

Vlastnosti a metody třídy TStream

Sice jsme si řekli, že třídu TStream bychom neměli přímo instanciovat, uvedeme si nyní podrobný přehled jejích vlastností a metod. Pokud se ptáte, proč máme ztrácet čas uváděním přehledu metod třídy, kterou nesmíme instanciovat (a tedy v praxi používat), pak odpověď je nad očekávání prostá.

Většina tříd, které jsou z TStream odděděny, používá v podstatě stejné metody a vlastnosti jako samotný TStream. Pouze je implementuje tak, aby pracovaly s konkrétním, zvoleným datovým médiem, které je danou třídou reprezentováno. Ale pokud v níže uvedeném přehledu například najdete informaci o tom, že třída TStream obsahuje metodu „Trhni_si_nohou“, pak vězte, že většina tříd uvedených v závěru předchozího odstavce (TFileSTream, TMemoryStream, TSocketStream apod.) bude obsahovat také metodu „Trhni_si_nohou“, díky níž budeme moci nařídit každému konkrétnímu zvolenému streamu (souborovému, paměťovému, síťovému), aby si bez obav trhl nohou. Metoda se může nanejvýš trochu lišit ve svých parametrech, takže kupříkladu síťovému streamu podáme v parametru IP adresu nohy, kterou si má trhnout, paměťovému streamu pak pro změnu zadáme buffer, v němž se jeho noha nalézá apod.

Začněme tedy popisem vlastností třídy TStream. Ten je mimořádně jednoduchý: obsahuje pouze dva záznamy, vlastnosti Size a Position. Oběma jsem se podrobně zabývali před týdnem.

Vlastnost Popis
Size Velikost streamu. Je používána především interními rutinami, a v samotné třídě TStream nemá praktický význam. Někteří potomci (např. TFileStream) ji však definují tak, že s její pomocí lze provádět praktické operace (například změnit velikost souboru – oř
Position Indikuje aktuální pozici, na níž ve streamu zrovna jsme. Následující operace čtení nebo zápisu bude realizována právě z této aktuální pozice.

Tolik k vlastnostem TStream. Následující tabulka se zabývá událostmi a je ve srovnání s vlastnostmi podstatně obsažnější. Neuvádí kromě toho žádné metody, které bychom neměli ručně volat, protože jsou používány interně jinými metodami.

Metoda Popis
CopyFrom(stream, počet) Používá se ke kopírování dat z jednoho streamu do druhého. CopyFrom(xx, 25) funguje tak, že do streamu, nad nímž CopyFrom zavoláte, zkopíruje 25 bajtů ze streamu xxx. CopyFrom se také postará o odpovídající modifikaci aktuálních pozic ve streamech. Vrátí
Read(buffer, počet) Abstraktní metoda určená pro čtení ze streamu. Read je konkrétní příklad metody, která je přetížena jednotlivými třídami potomků, a tak Read pro paměťový stream funguje jinak než Read pro diskový soubor nebo COM objekt. Obecně lze říct, že Read použijeme
ReadBuffer(buffer, počet) Další „čtecí“ metoda. Přečte zadaný počet bajtů do bufferu. Pokud nelze přečíst dopředu stanovený počet bajtů, je generována výjimka EReadError.
ReadComponent(komponenta) Používá se ke čtení komponent a jejich vlastností ze streamu. Streamováním komponent jsme se v našem seriálu dosud nezabývali.
ReadComponentRes(komponenta) Metoda podobná metodě ReadComponent, čte komponentu s jejími vlastnostmi ze streamu a ukládá ve formátu resource souboru (souboru se zdroji, viz např. díly 106 a navazující tohoto seriálu).
Seek(o_kolik, odkud) Důležitá metoda. Používá se k přesunu na zadanou pozici ve streamu. Parametr „o_kolik“ udává, o kolik bajtů se ve streamu chceme posunout, parametr „odkud“ pak říká, odkud má posuv započít: hodnota soFromBeginning znamená od začátku streamu, hodnota soFro
SetSize(nová_velikost) V samotné TStream nedělá nic, v některých potomcích je předefinován a může být použit pro nastavení velikosti streamu (je to v podstatě zápisová metoda pro vlastnost Size).
Write(buffer, počet) Abstraktní metoda určená pro zápis do streamu. Write je konkrétní příklad metody, která je přetížena jednotlivými třídami potomků, a tak Write pro paměťový stream funguje jinak než Write pro diskový soubor nebo COM objekt. Obecně lze říct, že Write použij
WriteBuffer(buffer, počet) Další „zápisová“ metoda. Zapíše zadaný počet bajtů z bufferu do streamu. Pokud nelze zaspsat dopředu stanovený počet bajtů, je generována výjimka EWriteError.
WriteComponent(komponenta) Používá se k zápisu komponent a jejich vlastností do streamu.
WriteComponentRes(komponenta) Metoda podobná metodě WriteComponent, zapisuje komponentu s jejími vlastnostmi do streamu, který je ve formátu resource souboru (souboru se zdroji).

Na závěr

Dnešní článek nabyl sice příliš „programátorský“, shrnul však základní informace, které jsme empirickou a praktickou formou svírali v předchozích částech seriálu. Jinak řečeno, podívali jsme se na souhrn základních vlastností a metod, které jsou k dispozici ve třídách určených pro práci se streamy.