Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi TList in Datei schreiben/lesen (https://www.delphipraxis.net/146576-tlist-datei-schreiben-lesen.html)

runningsoft 22. Jan 2010 22:21


TList in Datei schreiben/lesen
 
Hallo,

ich habe zur Speicherung von formatiertem Text (RichText-Format) einen Record:

Delphi-Quellcode:
TTextBauStein = record
    ID : integer;             //ID des Textbausteins
    fText : TStringList;      //Text aus RichEdit
   end;
Die verschiedenen Records speichere ich in einer TList:

Delphi-Quellcode:
var TextBausteinListe : TList;
Wie speichere ich die gesamte Liste in einer Datei bzw. lese die Datei wieder aus?

Ich hab es schon mit FileStream versucht, komme aber nicht so recht weiter. Besonders die Tatsache, dass die einzelnen Records ja keine feste Größe haben sondern durch die im Record verwendete Stringliste von unterschiedlicher Größe sind, bereitet mir beim Auslesen der Daten Probleme. Wie erkenne ich, wie groß ein abgespeicherter Datensatz ist?

Für einige Hinweise bzw. Codeschnipsel wäre ich dankbar.

Steffen

SirThornberry 22. Jan 2010 22:33

Re: TList in Datei schreiben/lesen
 
Wenn du nicht erkennen kannst wie groß ein gespeicherter Datensatz ist wäre es das einfachste du speicherst diese Information davor mit ab.

Astat 23. Jan 2010 01:27

Re: TList in Datei schreiben/lesen
 
Zitat:

Zitat von runningsoft
Wie speichere ich die gesamte Liste in einer Datei bzw. lese die Datei wieder aus?
Für .. Hinweise .. Codeschnipsel wäre ich dankbar.

Hallo runningsoft, anbei "Schnipsel"

Delphi-Quellcode:

program Project1;

{$APPTYPE CONSOLE}

uses
  windows,
  classes,
  sysutils;

type
  TTextBauStein = packed record
    ID : integer;             // ID des Textbausteins
    fText : TStringList;      // Text aus RichEdit
   end;
  PTextBauStein = ^TTextBauStein;

var
  TextBausteinListe : TList;
  ms: TMemoryStream;
  p: PTextBauStein;
  cbData: integer;
  sData: string;
begin
  ms := TMemoryStream.Create;
  TextBausteinListe := TList.create;

  //-- mit Dumydaten Füllen
  GetMem(p, SizeOf(TTextBauStein));
  p^.ID := 1;
  p^.fText := TStringList.Create;
  p^.fText.Add('FOO');

  //-- In TList Speichern
  TextBausteinListe.Add(p);

  //-- Aus TList ein Item auslesen und Speichern
  ms.Write(PTextBauStein(TextBausteinListe.Items[0])^, SizeOf(TTextBauStein));

{While noch Daten Da sind do BEGIN}

  //-- Länge der TStringList Daten (StringList.Text) ermitteln
  cbData := Length(PTextBauStein(TextBausteinListe.Items[0])^.fText.Text);

  //-- Länge in Stream speichern
  ms.Write(cbData, sizeof(integer));

  //-- TStringList Daten speichern
  ms.Write(PTextBauStein(TextBausteinListe.Items[0])^.fText.Text[1],
    Length(PTextBauStein(TextBausteinListe.Items[0])^.fText.Text));

{While noch Daten Da sind END}

  ms.SaveToFile('c:\out.dat');
  ms.Free;

  p^.fText.Free;
  TextBausteinListe.Free;
  freemem(p);
  cbData := 0;

  //-- nun alles vice versa neu einlesen
  ms := TMemoryStream.Create;
  TextBausteinListe := TList.create;
  GetMem(p, SizeOf(TTextBauStein));

  ms.LoadFromFile('c:\out.dat');
  ms.Read(p^ ,SizeOf(TTextBauStein));

  ms.Read(cbData, Sizeof(integer));

  p^.fText := TStringList.Create;
  setlength(sData, cbData);
  ms.Read(sData[1], cbData);
  p^.fText.Add(sData);
  TextBausteinListe.Add(p);

  writeln(IntToStr(PTextBauStein(TextBausteinListe.Items[0])^.ID));
  writeln(PTextBauStein(TextBausteinListe.Items[0])^.fText.Text);
  readln;
end.

lg. Astat

sx2008 23. Jan 2010 02:17

Re: TList in Datei schreiben/lesen
 
Ich denke, es ist ganz offensichtlich, dass der Record TTextBaustein einige Methoden braucht und deshalb in eine Klasse umgewandelt werden sollte.
Es bei einem Record zu belassen wäre unprofesionell.
Delphi-Quellcode:
type
  TTextBauStein = class(TPersistent)
  public
    ID : integer;             // ID des Textbausteins
    fText : TStringList;      // Text aus RichEdit
    construtor Create;
    destructor Destroy;override;

    procedure LoadFromStream(stream:TStream);
    procedure SaveToStream(stream:TStream);
  end;
Durch den Konstruktor und Destruktor übernimmt die Klasse die Verwantwortung ("Ownership") über die Stringliste.
Dies vereinfacht die Arbeit mit TTextBaustein.
Statt in TList werden die TTextBaustein-Objekte in einer TObjectList gehalten.

Die Daten werden mit der Technik gespeichert, die Astat im vorherigen Beitrag beschrieben hat:
Delphi-Quellcode:
procedure TTextBauStein.SaveToStream(stream:TStream);
var
  s : string;
  len : integer;
begin
  Assert(Assigned(stream));
  stream.WriteBuffer(ID, sizeof(ID));
  s := fText.Text;
  len := Length(s);
  //-- Länge in Stream speichern
  stream.WriteBuffer(len, sizeof(len));
  //-- TStringList Daten speichern
  stream.WriteBuffer(s[1], len);
end;
Man sieht sehr schön, wie die Anwendung von Objektorientierung den Sourcecode vereinfacht.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:51 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz