Co to s▒ te strumienie? Jak by to najpro╢ciej wyja╢niµ?
Ot≤┐ strumienie to ci▒g danych, kt≤ry mo┐e byµ zapisywany np. w
pliku. Wyobra╝ sobie tak▒ ksi▒┐kΩ adresow▒. Masz na formie listΩ
adres≤w oraz imion zgrupowanych np. na komponencie typu ListView.
Chcesz te adresy teraz zapisaµ tak jak to ma miejsce np. w Windowsowej
ksi▒┐ce adresowej. Na ko±cu tego artyku│u bΩdzie rozwi▒zanie tego
problemu - zapisywanie wszystkiego do jednego pliku i odczytanie. A
wszystko za pomoc▒ strumieni.
Podstawow▒ klas▒ dla strumieni jest klasa TStream. To
od niej wywodz▒ siΩ pozosta│e obiekty bΩd▒ce samodzielnym typem.
Oto one:
-
TFileStream - s│u┐y do operacji na plikach;
-
TMemoryStream - do operacji danych w pamiΩci
komputera;
-
TResourceStream - operuje na zasobach plik≤w;
-
TStringStream - s│u┐y do operacji na zmiennych
tekstowych ( String ).
W tej chwili pewnie nie wiesz jak to wszystko zastosowaµ
itp. Ale nie martw siΩ - zaraz wszystko stanie siΩ jasne gdy┐
wykorzystanie strumieni nie jest niczym nadzwyczajnym.
Np. wykorzystanie typu TResourceStream. Oto przyk│ad
wyci▒gniΩcia z naszego programu EXE bitmapy o nazwie 'MOJA', a nastΩpnie
zapisanie tej bitmapy na dysku:
var
S : TResourceStream;
begin
S := TResourceStream.Create(hInstance, 'MOJA', RT_BITMAP);
S.SaveToFile('C:\main.bmp');
S.Free;
Sam przyznasz, ┐e to nie jest nic trudnego, prawda?
Najpierw deklarowana jest zmienna typu "TResourceStream", a
nastΩpnie jest ona tworzona. W konstruktorze zmiennej pierwszym
parametrem jest uchwyt pliku, drugim nazwa zasobu, a ostatni parametr to
typ zasobu. Typy zasob≤w mo┐esz poznaµ w systemie pomocy Delphi pod
zak│adk▒ "TResourceStream".
No i nastΩpnie wyci▒gniΩty zas≤b zostaje zapisany na
dysku.
Tak jak opisa│em wy┐ej strumienie mog▒ tak┐e operowaµ
na plikach. Trzeba jednak podaµ w≤wczas tryb otwarcia pliku - np:
var
S : TFileStream;
begin
S := TFileStream.Create('C:\plik.txt', fmOpenWrite);
Pierwszym parametrem tego konstruktora jest nazwa pliku, kt≤rego bΩdzie
dotyczyµ operacja, a drugim parametrem jest w│a╢nie tryb otwarcia.
Ten parametr mo┐e mieµ nastΩpuj▒c▒ warto╢µ:
Parametr |
Opis |
fmCreate |
Tworzy nowy plik je┐eli
nie istnieje na dysku; |
fmOpenRead |
Otwiera plik jedynie do
odczytu; |
fmOpenWrite |
Otwiera plik do zapisu; |
fmOpenReadWrite |
Otwiera do zapisu lub do
odczytu; |
ªwietnie - je┐eli masz ju┐ plik otwarty mo┐esz
przyst▒piµ do operacji na tym w│a╢nie pliku.
Podstawowymi funkcjami s▒ polecenia zapisu i odczytu.
Robi▒ to funkcje zapisu i odczytu:
-
Write, WriteBuffer - zapisuje dane do pliku;
-
Read, ReadBuffer - odczyt;
R≤┐nica pomiΩdzy dwoma poleceniami wykonywuj▒cymi tΩ
sam▒ czynno╢µ jest taka, ┐e polecenia Read i Write to funkcje i
zwracaj▒ liczbΩ danych wpisanych do pliku. Przyk│adowy zapis rekordu
do pliku m≤g│by wygl▒daµ tak:
var
S : TFileStream;
Rec : record
Name : String;
ID : Byte;
end;
begin
Rec.Name := 'Adam';
Rec.ID := 2;
S := TFileStream.Create('C:\plik.txt', fmCreate);
S.WriteBuffer(Rec, SizeOf(Rec));
S.Free;
To spowoduje zapis danych do pliku. Mo┐esz teraz np.
dopisaµ do istniej▒cych danych kolejny rekord - s│u┐y do tego
polecenie Seek:
S := TFileStream.Create('C:\plik.txt', fmOpenWrite);
S.Seek(SizeOf(Rec), soFromEnd);
W tym wypadku polecenie Seek przesunie miejsce zapisu
danych na sam koniec. Pierwszym parametrem jest wielko╢µ danych - okre╢lone
jest to poprzez SizeOf. Kolejny parametr to miejsce w kt≤rym ma siΩ
rozpocz▒µ operacja zapisu. W tym wypadku bΩdzie to na samym ko±cu pliku.
Mo┐esz w tym miejscu podaµ dowoln▒ warto╢µ lub:
Do okre╢lenia ilo╢ci rekord≤w znajduj▒cych siΩ w
pliku mo┐esz zastosowaµ co╢ takiego:
Rozmiar := S.Size div SizeOf(Rec);
Zmienna Rozmiar bΩdzie zawieraµ ilo╢µ rekord≤w.
Zasada jest prosta: w│a╢ciwo╢µ Size okre╢la ilo╢µ bajt≤w
zapisanych w pliku - dziel▒c to przez rozmiar ( w bajtach ) rekordu
otrzymamy ilo╢µ rekord≤w znajduj▒cych siΩ w pliku.
Istnieje jeszcze polecenie Position, kt≤ra okre╢la
aktualn▒ pozycje w pliku.
To w│a╢ciwie wszystko co najwa┐niejsze.
Strumienie umo┐liwiaj▒ tak┐e zapisywanie do pliku
ustawie± komponent≤w - np. po│o┐enia komponentu na formie itp. Do
tego s│u┐▒ polecenia: WriteComponent oraz ReadCompoennt.
ProszΩ bardzo - zapisanie komponentu o nazwie "btnMove"
do pliku:
var
FileStream : TFileStream;
begin
if FileExists('setup.txt') then // jezeli istnieje plik
FileStream := TFileStream.Create('setup.txt', fmOpenWrite) else
FileStream := TFileStream.Create('setup.txt', fmCreate); //w przeciwnym wypadku stworz plik
FileStream.WriteComponent(btnMove); // zapisz ustawienia komponentu TButton
FileStream.Free; // zwolnij zmienna
W tym wypadku je┐eli plik nie istnieje to zostanie
stworzony, a je┐eli istnieje - zostanie jedynie otwarty do
zapisu.
Teraz odczyt wygl▒da bardzo podobnie:
procedure TMainForm.FormCreate(Sender: TObject);
var
FileStream : TFileStream;
begin
if not FileExists('setup.txt') then Exit; //jezeli plik nie istnieje - nie rob nic
FileStream := TFileStream.Create('setup.txt', fmOpenRead); //otworz tylko do odczytu
FileStream.ReadComponent(btnMove); // odczytaj ustawienia komponentu
FileStream.Free;
end;
Istnieje jeszcze jedna przydatna funkcja - CopyFrom.
Przedstawia siΩ ona nastΩpuj▒co:
function CopyFrom ( Source: TStream; Count: Longint ) : Longint;
S│u┐y ona do przypisania jednemu strumieniowi warto╢ci
drugiego strumienia.
Polecam ╢ci▒gniΩcie ╝r≤d│a programu
"Kartoteka", kt≤ry wykorzystuj▒c strumienie zapisuje do
pliku nazwΩ oraz e-mail. Jest to taka ksi▒┐ka adresowa.
Przydatne linki:
¼r≤d│a:
Adam Boduch