[delphi]Zapisywanie klasy

Odpowiedz Nowy wątek
2006-12-27 15:05

Rejestracja: 13 lat temu

Ostatnio: 13 lat temu

0

Witam!

Mam klasę

type
  TPlik=class
    count:integer;
    tablica:array of  string;
  end;

i nie wiem jak ją zapisać. Próbowałem już z BlockWrite i BlockRead, ale nie zadziałało.
Dzięki

Pozostało 580 znaków

2006-12-27 16:01

Rejestracja: 16 lat temu

Ostatnio: 7 lat temu

0

to może napisz co chcesz uzyskać :>


- Ciemna druga strona jest.
- Nie marudź Yoda, tylko jedz tego tosta.
Google NIE GRYZIE!
Pomogłem - kliknij

Pozostało 580 znaków

2006-12-27 16:17

Rejestracja: 13 lat temu

Ostatnio: 13 lat temu

0

Chcę uzyskać plik, który łatwo będzie można wczytywać i edytować
(coś w rodzaju zewnętrznego pliku zasobów)

Pozostało 580 znaków

2006-12-27 17:55

Rejestracja: 16 lat temu

Ostatnio: 10 lat temu

0

Nie wiem, czy zdajesz sobie sprawy z kilku rzeczy:

  • odróżniasz rekord od klasy
  • array of jest tablicą dynamiczną, więc zapisanie jej nie ogranicza się do podania adresu zmiennej i rozmiaru
  • string ma rozmiar dynamiczny (w przeciwności do string[n]) więc jej zapisanie też nie jest takie proste, by podać sam adres i rozmiar przez sizeof(zmienna) - trzeba się bardziej narobić.

Jak nie chce Ci się tego pisać ręcznie i dodatkowo, jeśli wskazana przez ciebie funkcjonalność jest jedną całością, polecam klasę TStringList - nie dość, że ma wszystko, co jest potrzebne do zarządzania stringami, to jeszcze ma gotowe funkcje zapisu/odczytu.


<font color="red">Konto porzucone</span>

Dzięki wszystkim forumowiczom za lata wspólnych dyskusji; miłej zabawy w programowanie!
Sławomir 'Szczawik' Włodkowski

Pozostało 580 znaków

2006-12-27 21:41

Rejestracja: 13 lat temu

Ostatnio: 13 lat temu

0

Nie musi to być klasa, tylko nie wiem które bardziej się nadaje.
A jak tablica będzie typu np TBitmap, albo jakiegoś mojego rekordu?

Pozostało 580 znaków

2006-12-28 00:08

Rejestracja: 16 lat temu

Ostatnio: 7 lat temu

0

to trzeba ręcznie (w sensie samemu kod wklepać) po kolei każdą komórkę tablicy zapisać do pliku i jeszcze dodatkowo zapisać sobie ile każda komórka zajmuje i/lub gdzie się zaczyna, żeby przy odczycie było wiadomo

na początek sugerował bym zapoznanie się z klasami pochodnymi od TStream (TMemoryStream, TFileStream) oraz z budową klasy TList oraz analizę klas pochodnych od TList (np. TObjectList, TComponentList) - zauważ, że wyglądają one prawie tak samo.

Jak już załapiesz jak to działa to tworzysz najpierw klasę, która będzie przechowywała pojedyńczy obiekt i na bazie tej klasy włąsną klasę TMyList = class(TList). Ma to tą zaletę, że masz od razu kilka metod, min. Add, Delete, Clear, IndexOf, Extract, First, Last, Insert, Move, Remove, Assign itd. Może na pierwszy rzut oka wydaje się to skąplikowane ale po ogarnięciu jest bardzo wygodne i praktyczne

Tu masz przykład z zapisem do listy rekordu


- Ciemna druga strona jest.
- Nie marudź Yoda, tylko jedz tego tosta.
Google NIE GRYZIE!
Pomogłem - kliknij

Pozostało 580 znaków

2006-12-28 00:13

Rejestracja: 16 lat temu

Ostatnio: 10 lat temu

0

Może przykładzik, do klasy zamieszczonej powyżej:

type
  TPlik=class
    Count:integer;
    Tablica:array of string;
  public
    procedure SaveToFile(FileName:TFileName);
    procedure LoadFromFile(FileName:TFileName);
  end;

{ TPlik }

procedure TPlik.LoadFromFile(FileName:TFileName);
var Handle:THandle;
    i:integer;
    len:integer;
    read:DWORD;
begin
Handle:=CreateFile(PChar(FileName), GENERIC_READ, 0, nil, OPEN_ALWAYS, 0, 0);
if (Handle<>INVALID_HANDLE_VALUE) then
  begin
  ReadFile(Handle, Count, sizeof(count), read, nil);
  SetLength(tablica, count);
  for i:=0 to count-1 do
    begin
    ReadFile(Handle, len, sizeof(len), read, nil);
    SetLength(tablica[i], len);
    ReadFile(Handle, PChar(tablica[i])^, len, read, nil);
    end;
  CloseHandle(Handle);
  end;
end;

procedure TPlik.SaveToFile(FileName:TFileName);
var Handle:THandle;
    i:integer;
    len:integer;
    written:DWORD;
begin
Handle:=CreateFile(PChar(FileName), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, 0, 0);
if (Handle<>INVALID_HANDLE_VALUE) then
  begin
  WriteFile(Handle, Count, sizeof(count), written, nil);
  for i:=0 to count-1 do
    begin
    len:=length(tablica[i]);
    WriteFile(Handle, len, sizeof(len), written, nil);
    WriteFile(Handle, PChar(tablica[i])^, len, written, nil);
    end;
  CloseHandle(Handle);
  end;
end;

Ogólna idea jest taka: najpierw zapisujesz ile co zajmuje, a potem dopiero dane tego czegoś. Najpierw ile elementów ma tablica, potem ile ma każdy element, dopiero na końcu dane tego elementu (tutaj stringu). Oczywiście robisz tak tylko w przypadku zmiennych/obiektów, które nie mają stałego rozmiaru.

Przy odczycie na odwrót. Odczytujesz ile elementów ma mieć tablica, alokujesz tablicę, ile ma mieć element poszczególnych stringów, alokujesz stringi, a dopiero na końcu, kiedy masz miejsce na dane, wczytujesz te - tutaj treść stringów.


<font color="red">Konto porzucone</span>

Dzięki wszystkim forumowiczom za lata wspólnych dyskusji; miłej zabawy w programowanie!
Sławomir 'Szczawik' Włodkowski

Pozostało 580 znaków

2006-12-28 10:49

Rejestracja: 13 lat temu

Ostatnio: 13 lat temu

0

Dzięki Szczawik!
Gdyby tablica była klasy TPicture albo TGraghic?
A tak w ogóle to klasy TObjectList, TComponentList w którym module się znajdują?

Pozostało 580 znaków

2006-12-28 11:42

Rejestracja: 16 lat temu

Ostatnio: 10 lat temu

0

To musisz ręcznie. Może przykład zapisu klasy z dwoma bitmapami:

  TPlik = class
  public
    bmp1:TBitmap;
    bmp2:TBitmap;
    constructor Create();
    destructor Destroy; override;
    procedure SaveToFile(FileName:TFileName);
    procedure LoadFromFile(FileName:TFileName);
  end;

{ TPlik }

constructor TPlik.Create;
begin
inherited;
bmp1:=TBitmap.Create;
bmp2:=TBitmap.Create;
end;

destructor TPlik.Destroy;
begin
bmp1.Free;
bmp2.Free;
inherited;
end;

procedure TPlik.LoadFromFile(FileName: TFileName);
var Str:TMemoryStream;
    FileStr:TFileStream;
    n:integer;
begin
Str:=TMemoryStream.Create;
FileStr:=TFileStream.Create(FileName, fmOpenRead);

FileStr.ReadBuffer(n, sizeof(n));
Str.CopyFrom(FileStr, n);
Str.Position:=0;
bmp1.LoadFromStream(Str);
Str.Clear;

FileStr.ReadBuffer(n, sizeof(n));
Str.CopyFrom(FileStr, n);
Str.Position:=0;
bmp2.LoadFromStream(Str);

FileStr.Free;
Str.Free;
end;

procedure TPlik.SaveToFile(FileName: TFileName);
var Str:TMemoryStream;
    FileStr:TFileStream;
    n:integer;
begin
Str:=TMemoryStream.Create;
FileStr:=TFileStream.Create(FileName, fmOpenWrite);

bmp1.SaveToStream(Str);
n:=Str.Size;
FileStr.WriteBuffer(n, sizeof(n));
Str.SaveToStream(FileStr);
Str.Clear;

bmp2.SaveToStream(Str);
n:=Str.Size;
FileStr.WriteBuffer(n, sizeof(n));
Str.SaveToStream(FileStr);

FileStr.Free;
Str.Free;
end;

Przykład użycia:

var Plik:TPlik;
begin
Plik:=TPlik.Create;
try
  Plik.bmp1.Assign(Image1.Picture.Bitmap);
  Plik.bmp2.Assign(Image2.Picture.Bitmap);
  Plik.SaveToFile('c:\plik.txt');
  Plik.bmp1.Assign(nil);
  Plik.bmp2.Assign(nil);
  Plik.LoadFromFile('c:\plik.txt');
  Image3.Picture.Bitmap.Assign(Plik.bmp1);
  Image4.Picture.Bitmap.Assign(Plik.bmp2);
except
  end;
Plik.Free;
end;

<font color="red">Konto porzucone</span>

Dzięki wszystkim forumowiczom za lata wspólnych dyskusji; miłej zabawy w programowanie!
Sławomir 'Szczawik' Włodkowski

Pozostało 580 znaków

2006-12-29 21:11

Rejestracja: 13 lat temu

Ostatnio: 13 lat temu

0

Dzięki!
A byłby jakiś sposób na dynamiczną tablicę typu TBitmap??

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0