Delphi - Strumienie - Informacje dodatkowe
Sat, 9 October 2004
#Informacje dodatkowe
Wstęp
Cały cykl artykułów "Delphi - strumienie" miał za zadanie zademonstrować w prosty sposób użycie poszczególnych typów tych użytecznych narzędzi. Nie obyło się jednak bez pewnych specyficznych "haczyków", które miały sposobność dokuczać w większości początkującym w tej dziedzinie. Dziś przedstawię informacje, których nie znaleźliście wcześniej. Będzie to uzupełnienie do poprzednich części artykułów, jak i zarazem ostatnia część cyklu.
Polecenie Seek
Omówię jako pierwsze właśnie to polecenie. Służy ono bowiem do zmiany pozycji kursora w pliku. Jak zapewne wiecie, przy opracowywaniu różnorakich dokumentów (np. poprzez Word, WordPad, AbiWord czy Notatnik) mamy do czynienia z kursorem. To taka "migająca pionowa kreseczka" (ujął by ktoś to bardziej fachowo ? ;). Dzięki niej, zawsze wiemy w którym miejscu w dokumencie aktualnie się znajdujemy, a tym samym gdzie pojawi się nowowpisywany tekst. Również w pamięciowych plikach, jakimi są zapewne strumienie, mamy do czynienia z takim zjawiskiem. Również tu, możemy wyobrazić sobie kursor tak jak to zostało opisane wcześniej. Dzięki niemu będziemy mogli kontrolować, gdzie mamy zamiar umieścić zapisywane dane. Polecenie Seek, jako takie ma trzy parametry, z których możemy w każdej chwili skorzystać. Oto one:
Parametr | Opis |
---|---|
parametr | pełniona funkcja |
soFromBeginning | Przenosi kursor na początek strumienia. |
soFromCurrent | Przenosi kursor do aktualnej pozycji Position. |
soFromEnd | Przenosi kursor na koniec strumienia. |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
strumien : TMemoryStream;
implementation
{$R *.dfm}
procedure TForm1.Button2Click(Sender: TObject);
begin
// Zapisanie danych do strumienia
memo1.Lines.SaveToStream(strumien);
// Wyczyszczenie komponentu Memo1
memo1.Clear;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// Po zapisie kursor jest na końcu strumienia dlatego cofamy go na początek
strumien.Seek(0, soFromBeginning);
// Odczytanie danych ze strumienia
memo1.Lines.LoadFromStream(strumien);
end;
initialization
strumien := TMemoryStream.Create;
end.
Powyższy kod powinien bezproblemowo przejść przez łaski kompilatora ;) i równie bezproblemowo powinien działać w praktyce. Spróbujcie jednak wyrzucić polecenie:strumien.Seek(0, soFromBeginning);
a program działać przestanie. Jak widzimy polecenie Seek() z powyższymi parametrami, cofa kursor na początek strumienia, dzięki czemu możemy odczytać dane. Co oznacza jednak pierwszy parametr ? Spróbujmy to wywnioskować z ogólnej budowy polecenia:function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
Na miejscu pierwszego prarametru widzimy nijakie "Offset". Jest to parametr który określa o ile ma zostać przesunięty kursor w stosunku do pozycji podanej w drugim parametrze. Mogło to zabrzmieć nieco niejasno, dlatego przytoczę przykład. Gdy wywołamy funkcję Seek z parametrami:Seek(5, soFromBeginning);
będzie to oznaczało, że umieszczamy kursor w strumieniu po piątym znaku licząc od początku. Przypuśćmy, że w strumieniu znajduje się tekst "Magazyn". Gdy wywołamy polecenie Seek() z parametrami Seek(0, soFromBeginning) i spróbujemy odczytać tekst ze strumienia, odczytane zostaną wszystkie dane, od początku, aż do końca, czyli "Magazyn". Gdybyśmy jednak wywołali funkcję Seek() z parametrami Seek(2, soFromBeginning) w wyniku próby odczytu dostaniemy jedynie "gazyn".
Jak zatem odczytać np. trzy ostatnie litery? Polecenie Seek() wywołane z parametrami Seek(0, soFromEnd); na niewiele się zda, ponieważ przesunie nam kursor na koniec strumienia, a za końcem nie ma już nic ;) Popatrzmy jeszcze raz na budowę Seek(). Szczególną uwagę zwróćmy na typ pierwszego parametru, jest to int64, a jak wiemy typ ten może przechowywać również wartości ujemne. Dlatego chcąc odczytać 3 ostatnie znaki musimy wywołać polecenie Seek() z parametrami:Seek(-3, soFromEnd);
Spowoduje to cofnięcie kursora o trzy miejsca "w lewo", czyli do tyłu, licząc od końca.
Właściwość Position
Co ciekawe instrukcja:Seek(0, soFromBeginning);
może zostać zastąpiona bardziej precyzyjną właściwością Position:Position := 0;
Analogicznie instrukcja np. Seek(84, soFormBeginning); jest równoznaczna z przypisaniem:Position := 84;
Czy nie łatwiej? Wydaje mi się, że tak.
Właściwość Size...
... jest właściwością tylko do odczytu i przechowuje aktualny rozmiar danych w strumieniu. W przypadku tekstu, każdy znak to, jak sobie przypominamy, jeden bajt. Dlatego w wypadku tekstu "Ala ma kota" właściwość Size będzie równa 11. Proste? Jasne, że tak. Dzięki temu możemy zastąpić polecenie:Seek(0, soFromEnd);
przypisaniem:Position := Size;
Zatem gdy chcielibyśmy odczytać dane od środka strumienia musimy podzielić rozmiar strumienia przez dwa:Position := Size div 2;
Zakończenie
To już wszystko na dzisiaj. Wspomnę jeszcze tylko o funkcji CopyFrom(). Jej budowa jest następująca:CopyFrom(Source: TStream; Count: Int64): Int64;
Za jej pomocą możecie kopiować dane z jednego do drugiego strumienia (jako pierwszy parametr podajemy strumień z którego chcemy skopiować dane, drugi parametr służy do określania wielkości danych które chcemy skopiować). Dodaje do artykułu
źródło, w którym pokazałem jak efektownie wykorzystać funkcje CopyFrom(). Aha, jeszcze jedna przydatna informacja! Jeśli w drugim parametrze funkcji CopyFrom() wpiszecie 0 to skopiuje się cała zawartość strumienia źródłowego.
To wszystko! Spotykamy się za miesiąc.





Podobne artykuly:
- Delphi - Strumienie - Wstęp
- Delphi - Strumienie - TFileStream
- Delphi - Strumienie - TStringStream
- Delphi - Strumienie - TMemoryStream
- Delphi - Strumienie - TResourceStream
- KillAd
- Delphi - Budowa modułu