Hlavní navigace

Squeak: návrat do budoucnosti (15)

Pavel Křivánek

Proudové třídy jsou pro praxi velmi důležité. Dnes se na ně zaměříme. Ukážeme si použití jejich nejdůležitějších metod a popíšeme si základy práce se soubory.

Proudy jsou objekty, které slouží ke zpřístupňování sekvencí objektů. Jedná se o instance tříd, které dědí z abstraktní třídy Stream. Samozřejmě ne všechny operace mají smysl pro všechny typy proudů. Například do proudu určeného pouze pro čtení nelze zapisovat apod. Jsou vždy provázány s nějakým sekvenčním datovým zdrojem, v němž si udržují informace o aktuální pozici.

next, next:, peek

Zpráva next vrátí další prvek z proudu. V okamžiku, kdy již v proudu žádné objekty nejsou, je vrácena hodnota nil.

Obdobně metoda next: vrací kolekci více objektů z proudu. Jejich počet je definován v parametru této zprávy. Typ vrácené kolekce je závislý na třídě, nad kterou je proud vytvořen.

stream := 'text' readStream.
stream next -> $t
stream next -> $e
stream next: 2 -> 'xt'

stream := #(1 2 3) readStream.
stream next -> 1
(stream next: 2) class -> Array

stream := #(3 2 6) asSortedCollection readStream.
items := stream next: 2.
items contents -> a SortedCollection(2 3)
items class -> SortedCollection

Pro přečtení předcházejícího prvku slouží metoda back.

Proudy obsahují celou řadu metod, které specifikují, jakým způsobem mají být přijímaná data interpretována. Můžete tak nalézt zprávy jako nextInt32, nextWord, nextNumber:, nextLittleEndi­anNumber:, int16 apod. Tyto metody často vyžadují binární proudy.

Zpráva peek má podobný význam jako next, ovšem nedochází ke změně aktuální pozice v proudu.

stream := 'text' readStream.
stream peek -> $t
stream peek -> $t

contents, upToEnd

Zpráva contents vrací všechny prvky v proudu. Metoda upToEnd vrací všechny prvky od aktuální pozice do konce proudu.

stream := 'text' readStream.
stream next.
stream contents -> 'text'

stream := 'text' readStream.
stream next.
stream upToend -> 'ext'

Zpracování proudu

Ke zpracování celého obsahu proudu můžeme použít starou známou metodu do:. Pracuje stejně jako u kolekcí. Zpracováván je vždy obsah do konce proudu počínaje aktuální pozicí.

stream := 'text' readStream.
stream next.
stream do: [:znak |
   Transcript
      show: (znak asciiValue bitXor: 2r10101010);
      space.
   "vypise 207 210 222"
]

Pohyb v proudu

Pro zjištění aktuální pozice v proudu slouží zpráva position. Začátek proudu má index 0. Pozici lze explicitně změnit zprávou position:. Pokud nová pozice přesahuje rozsah proudu, je vygenerována výjimka.

stream := 'text' readStream.
stream position -> 0
stream position: 2.
stream next -> $x

O tom, zda se již nacházíme na konci proudu, nás informuje zpráva atEnd vracející boolovskou hodnotu.

elements := OrderedCollection new.
[ stream atEnd ] whileFalse: [
      elements add: stream next
].

Na začátek proudu nás přemístí metoda reset.

stream := 'text' readStream.
stream next: 2.-> 'te'
stream reset.
stream next -> $t

Na konec proudu nás naopak přesune metoda setToEnd. Pro přeskakování specifikovaného počtu prvků proudu slouží metodaskip:. Její obdoba skipTo: se posunuje v proudu až do chvíle, kdy v něm nalezne objekt shodný s tím, který obdrží jako parametr.

Vyhledávání a porovnávání v proudu

Pro vrácení obsahu proudu po určitý objekt slouží zpráva upTo:. Pokud objekt není v proudu nalezen, je vrácen celý zbytek proudu.

stream := 'text' readStream.
stream upTo: $x -> 'te'

Podobně funguje i zpráva upToAll:, která ovšem neporovnává jediný objekt, ale celou kolekci objektů

stream := #(6 5 1 8 6 7 2) readStream.
stream upToAll: #(8 6) -> #(6 5 1)

stream := 'Answer a subcollection' readStream.
stream upToAll: 'collection' -> 'Answer a sub'

Zprávy nextMatchFor: a nextMatchAll: porovnávají následující prvky v proudu a vracejí příslušnou boolovskou hodnotu. Pozici v proudu mění při kladném i záporném výsledku. Metoda, která při selhání porovnání prvku v proudu neposune pozici, se jmenuje peekFor:Pokud je porovnávána kolekce objektů pomocí nextMatchAll: a dojde k neshodě, pozice v proudu se nezmění.

stream := 'text' readStream.
stream nextMatchFor: $t -> true
stream nextMatchAll: 'ex' -> true
stream nextMatchFor: $a -> false

Ke zjištění, zda proud obsahuje danou kolekci prvků, slouží metodamatch:. Při nalezení shody kolekce s proudem je pozice v proudu nastavena na následující objekt.

Zápis do proudu

K zápisu musí být proud přizpůsoben, nejlépe tak, že je instancí třídy WriteStream. Ta naopak vůbec neumožňuje čtení z proudu.

K zápisu do proudu slouží primárně metody nextPut: a nextPutAll:. Druhá uvedená přijímá jako parametr kolekci či proud.

stream := WriteStream on: String new
stream nextPut: $a.
stream nextPutAll: 'bcd'.
stream contents -> 'abcd'

Tyto dvě základní jsou samozřejmě rozšířeny mnoha dalšími specializovanými zprávami, např. next:putAll: vkládající specifikovaný počet prvků z dané kolekce apod.

K současnému čtení a zápisu do proudu je přizpůsobena třída ReadWriteStream. Po vytvoření je připravena k zápisu na konci proudu.

stream := ReadWriteStream with: 'abcd'.
stream reset.
stream next.
stream nextPut: $e.
stream contents -> 'aecd'

Vytvoření proudu

Proudy se nejčastěji vytvářejí nad kolekcemi nebo soubory. Některé způsoby jejich tvorby jsme si již ukázali.

K vytváření proudů se nesmí používat metoda new. Vždy jsou svázány se zdrojem dat a ten je nutno na počátku jejich existence specifikovat. K tomu slouží konstruktory on:, with:,on:from:to: vytvářející proud jen na části vstupní kolekce atd.

Další možností je použít konverzní metody readStream a writeStream, které jsou implementovány ve třídě SequenceableCo­llection, takže jim rozumí pole, řetězce, seznamy apod.

Proudy nad soubory

Pro práci se soubory se využívá třída FileStream a její potomci. K asociaci proudu s fyzickým souborem existuje několik zpráv, jejichž význam je patrný už ze selektorů. Před třídou FileStream se doporučuje upřednostňovat třídu StandardFileStream. FileStream má totiž abstraktní charakter (pokud se využívá přímo, deleguje StandardFileS­tream).

fileNamed:
otevře soubor daného jména pro čtení a zápis. Pokud tento soubor neexistuje, je vytvořen nový soubor. Pozice (i pro zápis) je nastavena na začátek souboru.
forceNewFileNamed:
otevře nový soubor daného jména pro čtení a zápis. Pokud tento soubor již existuje, je původní soubor smazán.
newFileNamed:
otevře nový soubor pro čtení a zápis. Pokud tento soubor již existuje, je o tom podána uživateli zpráva, a ten má možnost soubor přepsat či vybrat jiné jméno.
oldFileNamed:
otevře existující soubor pro čtení a zápis. Pokud tento soubor ještě neexistuje, má uživatel možnost jej vytvořit nebo zvolit jiné jméno souboru.
oldFileOrNoneNamed:
otevře existující soubor pro čtení. Pokud tento soubor neexistuje, je vráceno nil.
readOnlyFileNamed:
otevře existující soubor pro čtení. Pokud tento soubor neexistuje, má uživatel možnost zvolit jiné jméno.

Další užitečné metody, které poskytuje třída FileStream:

isAFileNamed:
prověří existenci souboru daného jména
fullName:
vrátí plné jméno souboru včetně cesty.

Hodit se může metoda contentsOfEnti­reFile, která vrací celý obsah souboru a rovnou se postará i o jeho zavření.

Pro další práci se soubory, jako je např. kopírování, slouží třída FileDirectory a její platformně specifické podtřídy.

Zavírání souborů

Pro zavírání souborů se používá zpráva close. Pokud je reference na soubor zrušena, postará se finalizační mechanismus o jeho uzavření. Nicméně – především pokud si se soubory hrajete ve Workspace – se vám může stát, že na neuzavřený soubor bude stále odkazovat nějaká zapomenutá reference. V tom případě jej již pravděpodobně znovu neotevřete, nebudete schopni ho smazat apod.

U běžných programů, pokud nejsou ukončeny korektně, se o uvolnění prostředků stará operační systém. Pokud vinou chyby ve vaší aplikaci nezhavaruje celý Squeak, k uzavření otevřených souborů nedojde.

V takovém případě je nutné nasadit některou z technik pro vyhledávání a práci se zapomenutými referencemi. Nejjednodušší je použít např. příkaz

StandardFileStream inspectAllSubinstances

a v otevřeném inspektoru zapomenuté soubory vyhledat a zaslat jim zprávu close.

Konce řádků

Squeak má své kořeny na počítačích společnosti Apple. Díky tomu nepoužívá standardně pro konce řádků znak LF ani dosovskou kombinaci CR LF, ale znak CR. V některých specifických situacích se můžete setkat s problémy, k jejichž řešení může pomoci např. třída CrLfFileStream.

Tímto jsme problematiku proudů ve Squeaku ještě zdaleka nevyčerpali. Neméně zajímavé jsou specializované proudy, komprimované proudy, sokety, image segmenty apod. O nich ale snad někdy příště.

Našli jste v článku chybu?

19. 5. 2004 18:41

vj (neregistrovaný)

Inu, reflektivita a exploratory programming. Stará to LISPovská tradice, kterou Smalltalk dále rozvinul.

18. 5. 2004 16:54

Jirka (neregistrovaný)

jak prosté.. díky...

btw: tohle a podobné věci se mi na Squeaku (st obecně) velmi líbí... Nevím, jak bych se nějakého jiného prostředí zeptal kolik je právě otevřených souborů a ještě k tomu bych mohl __takhle jednoduse__ kteremukoliv z nich poslat zpravu... uzasne...



Měšec.cz: Exekuční poradna: ptejte se online

Exekuční poradna: ptejte se online

DigiZone.cz: Sat novinky: slovenská TV8 HD i ruský NTV Mir

Sat novinky: slovenská TV8 HD i ruský NTV Mir

DigiZone.cz: R2B2 a Hybrid uzavřely partnerství

R2B2 a Hybrid uzavřely partnerství

120na80.cz: Boreliózu nelze žádným testem prokázat

Boreliózu nelze žádným testem prokázat

Root.cz: Nová třída SD karet A1 s vysokým výkonem

Nová třída SD karet A1 s vysokým výkonem

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte

Podnikatel.cz: Chaos u EET pokračuje. Jsou tu další návrhy

Chaos u EET pokračuje. Jsou tu další návrhy

Lupa.cz: Insolvenční řízení kvůli cookies? Vítejte v ČR

Insolvenční řízení kvůli cookies? Vítejte v ČR

Podnikatel.cz: E-Ježíšek si zařádí: nákupy od 2 do 5 tisíc

E-Ježíšek si zařádí: nákupy od 2 do 5 tisíc

120na80.cz: Horní cesty dýchací. Zkuste fytofarmaka

Horní cesty dýchací. Zkuste fytofarmaka

Podnikatel.cz: Vládu obejde, kvůli EET rovnou do sněmovny

Vládu obejde, kvůli EET rovnou do sněmovny

DigiZone.cz: Ohrozí Freedom TV přechodové sítě?

Ohrozí Freedom TV přechodové sítě?

Vitalia.cz: Pamlsková vyhláška bude platit jen na základkách

Pamlsková vyhláška bude platit jen na základkách

Vitalia.cz: Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

Lupa.cz: Propustili je z Avastu, už po nich sahá ESET

Propustili je z Avastu, už po nich sahá ESET

Vitalia.cz: Proč vás každý zubař posílá na dentální hygienu

Proč vás každý zubař posílá na dentální hygienu

120na80.cz: 5 nejčastějších mýtů o kondomech

5 nejčastějších mýtů o kondomech

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

Podnikatel.cz: Chtějte údaje k dani z nemovitostí do mailu

Chtějte údaje k dani z nemovitostí do mailu