artykuły

Delphi - Strumienie - TStringStream

20:36
pon, 12 lipiec 2004
Artykuł opisuje na przykładach działanie i zastosowania strumieni typu TStringStream. W prosty sposób wyjaśnia jak uniknąć częstych błędów związanych ze strumieniami.

#2 TStringStream

Wstęp

Wiele jest rzeczy w Delphi, z których nigdy nie skorzystamy - zapewniam Was, że strumienie do nich nie należą. Strumieniem którym się zajmiemy w niniejszej części jest strumień typu TStringStream. Kto "uważnie przejrzał" ;) pierwszą część cyklu, wie zapewne, że umożliwia on przeprowadzanie operacji na zmiennych tekstowych. Ten który zaczął od razu od części #2 może to samo wywnioskować z nazwy. No dobrze, ale w czym ten strumień może nam pomóc. Oczywiście, zamiast prawić rozległe teorię, proponuje skorzystać z przykładu w celu ustabilizowania wiedzy zawartej w połączeniach post-synaptycznych waszych neuronów (nie martwcie się - ja też nie rozumiem ;) Innymi słowy popatrzcie na przykład :

Aby zadeklarować strumień typuTStringStreamnależy dopisać po słówku var: var strumien : TStringStream; Niestety taki kod nie będzie jeszcze działać. Do tej pory "powiedzieliśmy" kompilatorowi, że gdzieś w kodzie będziemy chcieli skorzystać z takiej zmiennej. Należy jeszcze zmienną utworzyć. Zapytacie pewnie dlaczego jeśli chcemy zadeklarować zmiennąxjakointegernie tworzymy jej, a zmienną typuTStringStreammusimy stworzyć aby jej użyć? var x : integer; begin x := 17; Zauważcie, że jest między nimi spora różnica, jedno zawiera na początku literęT, a dokładniejTStringStream. Ktoś kiedyś rzekł, żeTnależy pisać przed nazwami klas. Tak się przyjęło i tak jest do tej pory. Klasy zawsze tworzymy po zadeklarowaniu. Tak więc musicie zapamiętać - ten typ tak ma ;)
Wracamy do tematu. Aby przygotować naszą zmiennąstrumiendo użycia w pełnym tego słowa znaczeniu, musimy zmienną stworzyć (wszyscy wiedzą dlaczego). Piszemy więc : var strumien : TStringStream; begin strumien := TStringStream.Create('do czego służy ten tekst?'); Jak widzimy, po słówkuvardeklarujemy zmiennąstrumientypuTStringStream. Następnie tworzymy ją poprzez przypisanie :
strumien := TStringStream.Create('do czego służy ten tekst?');Takie przypisanie pozwoli nam już skorzystać z możliwości jakie oferuje namTStringStream. Zanim zaczniemy odkrywać nowe możliwości tego rozwiązania, przypatrzmy się budowie funkcjiTStringStream.Create(), czyli tak zwanegokonstruktora. Prezentuje się ona następująco:
TStringStream.Create(AString: string);Zastanowiła Was pewnie jedna rzecz. Co należy wpisać w miejsceAString : string? Jak widzimy,AStringjest zmienną łańcucha znakówstring, więc jako parametr musimy nadać jakiś tekst. Ale do czego nam on posłuży ? Hmm... var strumien : TStringStream; begin strumien := TStringStream.Create('do czego służy ten tekst?'); ...co by się stało gdybyśmy teraz dopisali jakąś funkcję, która sczyta nam zawartość naszego strumienia i wyświetli go np. w komunikacie? Zobaczmy : var strumien : TStringStream; begin strumien := TStringStream.Create('do czego służy ten tekst?'); ShowMessage(strumien.DataString); strumien.Free; 3-cia linia, a właściwie 5-ta, zawiera w sobie dziwne polecenie -DataString. Do czego może ono służyć? Spróbujmy uruchomić program (F9). I co? Otrzymaliśmy komunikat "do czego służy ten tekst?". I co? Wiemy już do czego służy łańcuch znakówAStringużyty przy tworzeniu naszego strumienia i domyślamy się również znaczenia poleceniaDataString.
Łańcuch znaków, który musimy podać przy tworzeniu strumienia służy do nadania jakiejś początkowej zawartości naszemu strumieniowi. Możemy wpisać jako parametr coś takiego:strumien := TStringStream.Create('');Spowoduje to utworzenie pustego strumienia.
PolecenieDataStringjak się zapewne domyślacie pozwala nam odczytać całą zawartość strumienia. W naszym wypadku wartość nadaną przy tworzeniu strumienia, czyli "do czego służy ten tekst?".
Oczywiście na końcu naszego krótkiego programu musimy zwolnić strumień. Warto tego przestrzegać, choć w przypadku pojedynczej procedury (gdzie raz sczytujemy czy zapisujemy dane) jest to nieobowiązkowe. Pamiętać jednak nie zawadzi. Dlatego zachęcam do zwalniania strumieni po ich użyciu. W ten sposób unikniemy przykrych niespodzianek przy uruchamianiu programu.

Write

Co jednak w przypadku gdy chcemy zapisać do strumienia jakieś nowe dane? W takim przypadku posługujemy się poleceniemWrite. Ma ono następującą budowę:function Write(const Buffer; Count: Longint): Longint;Jak widzimy jest to funkcja. Analogicznie jak w przypadku strumieni typuTFileStreamzwraca ona ilość zapisanych danych. Pierwszy parametr przechowuje dane do zapisania, natomiast drugi parametr ilość danych które funkcja ma zapisać.
Gdy jako parametry funkcji podamy:zapisane := strumien.Wrtie('Magazyn @t', 3);Zapisze ona do strumienia tylko słowo:

Mag
	
Aby tak się nie działo możemy zastosować następującą składnię:zapisane := strumien.Write('Magazyn @t', Length('Magazyn @t'));Spowoduje to zapisanie całego tekstu przeznaczonego do zapisania. Zmienna 'zapisane' zawiera w tym wypadku ilość danych zapisanych do pliku.
Pisanie jednak dwa razy tego samego tekstu w funkcji jest bardzo niewygodne, dlatego opracowano procedurę:

WriteString

Procedura ta, podobnie jak jej siostra zapisuje do pliku tekst. Jest jednak mała różnica - nie zwraca ona żadnych danych (jest procedurą), ani nie potrzebuje określania wielkości zapisywanych danych. Jedynym jej parametrem jest tekst jaki ma zapisać do strumienia. Przyjrzyjmy się zatem budowie tej bardzo praktycznej procedury:procedure WriteString(const AString: string);Korzystamy z niej w następujący sposób :strumien.WriteString('Magazyn @t');To wszystko, nic nie trzeba więcej robić! Co prawda dużo częściej będziecie korzystać z proceduryWriteStringniż ze zwykłej funkcjiWrite, ale ważna jest znajomość obu tych metod.
Pokuszę się o modyfikacje naszego programu : var strumien : TStringStream; begin strumien := TStringStream.Create('do czego służy ten tekst?'); strumien.WriteString('Magazyn @t'); ShowMessage(strumien.DataString); strumien.Free; Teraz uważajcie! Komunikat który się wyświetli po starcie tego programu nie będzie wbrew pozorom zwierał tekstu:do czego służy ten tekst?Magazyn @t...ale w zawartości komunikatu pojawi się samo:Magazyn @tDlaczego? Otóż wartość początkowa nadawana przy tworzeniu strumienia ma to do siebie, że jest usuwana wraz z pierwszym zastosowaniem jakiejś funkcji zapisującej (np.WriteString). Gdybyśmy jednak dodali kolejną linię : var strumien : TStringStream; begin strumien := TStringStream.Create('do czego służy ten tekst?'); strumien.WriteString('Magazyn @t'); strumien.WriteString('-numer 42'); ShowMessage(strumien.DataString); strumien.Free; ...to nasz komunikat wyświetliłby coś takiego:Magazyn @t-numer 42Jak widać na powyższym przykładzie, usuwanie poprzedniej wartości przez funkcję zapisującą dotyczy tylko i wyłącznie wartości początkowej nadawanej przy tworzeniu strumienia. Mam nadzieję, że rozumiecie. Zanim jednak ostatecznie przydusimy klawisz F9, radzę popatrzeć na funkcję odczytujące dane ze strumienia. Pierwszą z nich jest funkcjaRead, następna toReadStringi właściwośćDataString.

Read

Funkcjareadsłuży do odczytu danych z pliku. Jej budowa prezentuje się następująco:function Read(var Buffer; Count: Longint): Longint;Jak widzimy - pierwszym parametrem jest tzw. bufor, czyli zmienna, która będzie przechowywała odczytane już dane. Drugim parametrem jest ilość danych które mają zostać odczytane. Funkcjareadzwraca ostatecznie ilość udanie odczytanych danych (w bajtach). Aby z niej skorzystać musimy zadeklarować najpierw zmienną, która będzie buforem, a po słowiebeginumieścić funkcjęRead, która odczyta nam zawartość strumienia.
Aby odczytać całą zawartość, funkcja może mieć jako drugi parametr podaną maksymalną wielkość danych jaką zmiennabufor_tekstowyjest zdolna w sobie zmieścić :SizeOf(bufor_tekstowy);Gwarantuje nam to odczytanie wszystkich danych. Oczywiście gdybyśmy chcieli odczytać tylko trzy pierwsze litery - nie ma problemu, wystarczy tylko jako drugi parametr funkcjiReadpodać 3.
Oczywiście tak jak w przypadku funkcji zapisujących, istnieje prostsza metoda, mianowicie funkcjaReadStringlub właściwośćReadData.

ReadString

Funkcja ta, pozwala nam odczytywać zawartość strumienia dużo prościej, bo bez deklarowania niepotrzebnych zmiennych. Popatrzcie jak jest zbudowana:function ReadString(Count: Longint): string;Jak widzimy, pierwszym i jedynym parametrem funkcji jest ilość danych do odczytania. Ostatecznie funkcja zwraca odczytane dane. Jak jednak odczytać przy pomocy tej funkcji całą zawartość strumienia ? Spróbujcie tak : var strumien : TStringStream; begin strumien := TStringStream.Create('do czego służy ten tekst?'); strumien.WriteString('Magazyn @t'); strumien.Position := 0; ShowMessage(strumien.ReadString(strumien.Size)); strumien.Free; Pewnie zauważyliście nową instrukcję -Position. Zapomniałem wcześniej zaznaczyć, określa ona aktualną pozycję kursora w strumieniu. Jeśli zatem chcemy czytać od początku ustawiamy :strumien.Position := 0;Jeśli tego nie zrobimy - klapa. Domyślacie się dlaczego? FunkcjaWriteString()przesuwa nam kursor o tyle miejsc ile zapisuje liter tekstu. Zatem po wykonaniu funkcjiWriteString, w powyższym przypadku kursor utknie na 10-siątej pozycji i stąd (wzwyż) będzie próbowała następnie odczytać dane funkcjaReadString(), dlatego nic nie zobaczymy w komunikacie. O właściwościPosition, tak jak iSeekorazSizebyć może powiemy sobie jeszcze w ostatniej części cyklu. Póki co wyjaśnię jeszcze co zawiera właściwośćstrumien.Size;Otóż za jej pomocą odczytamy wielkość danych w strumieniu. Czyli w tym wypadku 10.

DataString

Właściwość (tak, tak właściwość)DataStringpozwala nam odczytać całą zawartość strumienia za pomocą jednej instrukcji. Przechowuje ona dane zawarte w strumieniu. Możemy ją wykorzystywać jako zmienną, ale tylko do odczytu. Nie da się w niej zapisywać żadnych danych.

Zakończenie

Jest wiele innych funkcji, które pozwalają sprawnie operować na strumieniach. W tym cyklu postaram się wyróżnić te najważniejsze. Będę przekazywał również przydatne porady, które pozwolą Wam zaoszczędzić czas na "odkrywaniu" rzeczy odkrytych nie zawsze przyjemną metodą prób i błędów. Wiem ile czasu może stracić programista na szukaniu odpowiedniego rozwiązania. Tutaj jednak żaden podręcznik, żaden kurs, żaden artykuł nie będzie lepszy od wypróbowanej już nauki na błędach...

12345
Delphi - Strumienie - TStringStream Autor opinii: Czytelnicy, data przesłania: 0

Podobne artykuly:

Skomentuj

Aby zamieścić komentarz, proszę włączyć JavaScript - niestety roboty spamujące dają mi niezmiernie popalić.






Komentarze czytelników

    Nie ma jeszcze żadnych komentarzy.
    Dexter