AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi TStringList und Add-/InsertObject (Verständnisprobleme)
Thema durchsuchen
Ansicht
Themen-Optionen

TStringList und Add-/InsertObject (Verständnisprobleme)

Ein Thema von Karsten · begonnen am 5. Sep 2003 · letzter Beitrag vom 8. Sep 2003
Antwort Antwort
Seite 1 von 2  1 2      
Karsten

Registriert seit: 5. Sep 2003
56 Beiträge
 
Delphi 6 Personal
 
#1

TStringList und Add-/InsertObject (Verständnisprobleme)

  Alt 5. Sep 2003, 15:58
Verständnisprobleme
-------------------

Ähnlich wie in 'TStringList-Objekte auslesen' möchte ich zum speichern von Daten eine StringList benutzen.

Delphi-Quellcode:
type
  TDataSet = class(TObject)
  public
     Data1 : String;
     Data2 : String;
     u.s.w.
  end;


var
  DataSetList : TStringList;
Bisher war TDataSet als record definiert und beim schreiben in die String-List musste jedesmal die Startposition berechnet werden.
In der Hoffnung dieses verhindern zu können versuche ich die Datenstruktur auf 'Object' umzustellen (siehe oben) und die InsertObject und AddObject Eigenschaften der String-List zunutzen.

Daten in string-list speichern:
-------------------------------
Delphi-Quellcode:
procedure DataSetSpeichern;
var
  Position : Integer;
  TempDataSet: TDataSet;
begin
  TempDataSet := TDataSet.Create;

  <...Daten von Eingabe-Form lesen, Rückgabe ist TempDataSet...>

  <...Position bestimmen...>

  DataSetList.InsertObject(Position, '<text>', TempDataSet);

  TempDataSet.Free;
end;
Ich habe mir während des speicherns in die String Liste die Daten angesehen die gespeichert wurden und musste feststellen daß eigentlich nur der '<text>' in der liste auftauchte.
Frage: Was wird hier eigendlich gespeichert und wo ist der Rest der Daten die sich in TempDataSet (TDataSet) befanden ?

Daten aus string-list lesen:
----------------------------
Delphi-Quellcode:
function DataSetLesen(Position: Integer): TDataSet;
begin
  TempDataSet := DataSetList.Objects[Position] as TDataSet;
end;
Beim auslesen der Daten klappt es gar nicht. Die procedure die 'DataSetLesen' aufruft beinhaltet natürlich auch 'TempDataSet := TDataSet.Create;' und 'TempDataSet.Free;' wird erst dann aufgerufen
wenn die Daten komplett abgearbeitet sind.

Kann aber genau das mein Problem sein ('TempDataSet.Free;') ? Meine Vermutung ist daß möglicherweise nur ein Pointer in der String List gespeichert wird und ich beim aufrufen des '.Free' statements das ziel des Pointers vernichte.

Desweiteren würde ich mich über Informationen über Speichern und Lesen solcher daten in files freuen.

Danke und schönes Wochenende,

Karsten

[edit=Daniel B]Delphi-Tags korrigiert. Mfg, Daniel B[/edit]
  Mit Zitat antworten Zitat
neolithos

Registriert seit: 31. Jul 2003
Ort: Dresden
1.386 Beiträge
 
Delphi 7 Architect
 
#2

Re: TStringList und Add-/InsertObject (Verständnisprobleme)

  Alt 5. Sep 2003, 16:11
Zitat:
TempDataSet.Free;
Das ist dein Problem. Denn in der StringListe werden nur Verweise auf das Object gespeichert und nicht das Object selbst. (Hast du vorher VB programmiert, da würde sowas funktionieren).

Tipp für den Richtigen weg:

Erweitere TDataSet (dieser Name ist unglücklich da es schon eine Delphi-Klasse mit diesen Namen gibt) um ein Feld Caption und verwende statt TStringList TObjectList (bzw. einen Nachfahren davon). Diese hält das Object und verwaltet es. Trotzdem diese erste Zeile meines Positings lassen.

Das speichern kann man dann auch ohne weiteres impl..

Falls du die Caption als Mapper verwendest so kann man in dem abgeleiteten Object eine solche Funktion implementieren.

Schreib mal was du genau willst, dann sehen wir weiter!
- ciao neo -
Es gibt niemals dumme Fragen, sondern nur dumme Antworten!
  Mit Zitat antworten Zitat
Karsten

Registriert seit: 5. Sep 2003
56 Beiträge
 
Delphi 6 Personal
 
#3

Re: TStringList und Add-/InsertObject (Verständnisprobleme)

  Alt 5. Sep 2003, 16:39
Mein ziel ist das Verwalten (lesen von files, speichern in files, hinzufügenvon Daten, entfernen von Daten und lesen von Daten) von Daten vom Typ wie ich sie als (dummerweise) TDataSet definiert habe; und das
in unbestimmter Menge.

Die StringList habe ich nur gewählt weil man relativ einfach die Daten aus einem File einlesen kann und genauso speichern.

...LoadFromFile
...SaveToFile

Das war zu dem Zeitpunkt wo ich mit angefangen habe mit Delphi zu arbeiten.

Irgendwann habe ich festgestellt das eine StringList auch die Möglichkeit von ...InsertObject bietet und wollt diese ausprobieren um mir die ständige Bestimmung der Position (wo fängt der Datensatz an ?) zu ersparen.

Leiser fehlten mir wesentliche Informationen über die Nutzung von StringListen mit Objecten.

Leider kann ich über TObjectList in meinem Delphi Buch auch nichts finden, werde es aber ausprobieren. Ansonsten ist mal ein neues Buch angesagt.

Danke,
Karsten
  Mit Zitat antworten Zitat
neolithos

Registriert seit: 31. Jul 2003
Ort: Dresden
1.386 Beiträge
 
Delphi 7 Architect
 
#4

Re: TStringList und Add-/InsertObject (Verständnisprobleme)

  Alt 5. Sep 2003, 16:51
Ich mach das wiefolgt...

Delphi-Quellcode:
TBlabla = class
public
  constructor Create; // erzeugt neues Object
  constructor Load(stm : TStream); virtual; // lädt object aus Datenstrom
  procedure Store(stm : TStream); virtual; // speichert object in D-Strom
end;

TBlaBlaList = class
public
  constructor LoadFromFile(asFileName : String); virtual;
  constructor LoadFromStream(stm: TStream); virtual;
  procedure SaveToFile(asFileName : String); virtual;
  procedure SaveToStream(stm: TStream); virtual;
end;
Das ist aber schon tief im Nähkästchen
- ciao neo -
Es gibt niemals dumme Fragen, sondern nur dumme Antworten!
  Mit Zitat antworten Zitat
Karsten

Registriert seit: 5. Sep 2003
56 Beiträge
 
Delphi 6 Personal
 
#5

Re: TStringList und Add-/InsertObject (Verständnisprobleme)

  Alt 6. Sep 2003, 00:08
Ich denke daß ich schon einen Schritt weiter bin, aber mit dem Speichern / Lesen in / aus eine(r) Datei bin ich kläglich gescheitert.

Delphi-Quellcode:
type
  TDaten = class(TObject)
  public
     Daten1 : string;
     Daten2 : string;
     Daten3 : string;
  end;

type
  TDatenListe = class(TObjectList)
  public
    procedure WriteToFile(DatenListe: TDatenListe; FileName: String);
    procedure ReadFromFile(DatenListe: TDatenListe; FileName: String);
  end;

var
  DatenListe : TDatenListe;
Die folgenden Proceduren habe ich aus einem Handbuch kopiert und auf meie Bedürfnisse angepasst. Angeblich soll das funktionieren, wobei man im Original Arrays mit der Variante gespeichert hat. Die Tatsache das die Daten nicht gespeichert werden lässt mich zum Schluß kommen, daß sie (die Proceduren) absolut fehlerhaft sind oder sich noch prinzipielle Fehler im Aufsetzen der Daten bzw. in der Handhabung befinden . Habe mich vorher noch nie mit Streams befasst.

Delphi-Quellcode:
procedure TDatenListe.WriteToFile(DatenListe: TDatenListe; FileName: String);
var
  DatenStream: TFileStream;
begin
  if FileExists(FileName) then
  begin;
    try
      DatenStream := TFileStream.Create(FileName, fmOpenWrite);

      DatenStream.WriteBuffer(DatenListe, SizeOf(TDatenListe));

      DatenStream.Free;
    except
      MessageDlg('Fehler beim Schreiben der Daten', mtError, [mbOK], 0);
    end;
  end
  else
  begin;
    try
      DatenStream := TFileStream.Create(FileName, fmCreate);

      DatenStream.WriteBuffer(DatenListe, SizeOf(TDatenListe));
    except
      MessageDlg('Fehler beim Schreiben der Daten', mtError, [mbOK], 0);
    end;
    DatenStream.Free;
  end;
end;
Delphi-Quellcode:
procedure TDatenListe.ReadFromFile(DatenListe: TDatenListe; FileName: String);
var
  DatenStream: TFileStream;
begin
  try
    DatenStream := TFileStream.Create(FileName, fmOpenRead);

    DatenStream.Position := 0;
    DatenStream.ReadBuffer(DatenListe, SizeOf(TDatenListe));
  except
    MessageDlg('Fehler beim Lesen der Daten', mtError, [mbOK], 0);
  end;
  DatenStream.Free;
end;
Schreiben:
DatenListe.Insert(<Position>, Daten) Löschen:
DatenListe.Delete(<Position>) Ändern:
Delphi-Quellcode:
DatenListe.Delete(<Position>)
DatenListe.Insert(<Position>, Daten)
Lesen:
??? Element aus DatenListe an <Position> in Daten einlesen [edit=Daniel B]Delphi-Tags korrigiert. Mfg, Daniel B[/edit]
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.117 Beiträge
 
Delphi 11 Alexandria
 
#6

Re: TStringList und Add-/InsertObject (Verständnisprobleme)

  Alt 6. Sep 2003, 00:39
Moin Karsten,

Du versuchst ein Objekt vom Typ TDatenliste zu speichern, also inklusive aller Methoden, also nicht nur die Daten.
Das heisst, Du müsstest zum Speichern die Daten alleine bereitstellen.
SizeOf(TDatenListe) gibt übrigens vier zurück, da TDatenListe ein Objekt ist, und somit die Grösse die eines Pointers ist.

Warum TDaten bei Dir ein Objekt ist, und kein Record bzw. packed record, kann ich im Moment nicht nachvollziehen.
Dann könntest Du eine Variable vom Typ TDaten Schreiben, mit SizeOf(TDaten). Dass könnte dann grundsätzlich funktionieren, wobei der Typ String auch wieder ein Problem darstellt, da strings dynamische Arrays, und somit auch wieder Pointer sind. Die von Dir genannte Struktur wäre also, als packed record, 12 Byte gross.
Strings müsstest Du dann also entweder als ShortStrings einbauen (mit Längenangabe, aber nur maximal 255 Stellen), oder mittels einer Routine schreiben, die den Inhalt ausliest, und die Längen berücksichtigt.

Das Schreiben könnte z.B. so aussehen:
(hier nur die Änderungen, create usw. fehlt)

Delphi-Quellcode:
type
  TDaten = packed record
    dwLen1 : DWORD;
    sValue : string;
    //...
  end;

var
  tdWork : TDaten;

begin
  // erst einmal die Länge merken
  tdWork.dwLen1 := length(tdWork.sValue);
  // Vier Byte schreiben, da ein DWORD 4 Byte gross ist
  DatenStream.Write(tdWork.dwLen1,4);
  // Nur den String schreiben, wenn er etwas enthält
  if tdWork.dwLen1 > 0 then begin
    // Den String ab der ersten Stelle schreiben
    // Ohne [1] funktioniert es nicht, da dieser Parameter nicht typisiert ist
    DatenStream.Write(tdWork.sValue[1],tdWork.dwLen1);
  end;
end;
Die Längen solltest Du auf jeden Fall mit speichern (müssen allerdings nicht in TDaten enthalten sein), damit Du auch bei leeren Strings weisst was zu tun ist.
Wichtig: Beim Auslesen muss der auszulesende String vor dem Auslesen schon auf die richtige Länge bebracht werden, z.B. mit SetLength.
Was übrigens noch fehlt, ist der Resourcenschutzblock try/finally. Damit müsste sichergestellt werden, dass das Dateihandle auch wieder freigegeben wird.

Beispiel:

Delphi-Quellcode:
  // Resource belegen
  DatenStream := TFileStream.Create(....);
  try
  // Mach was mit DatenStream
  finally
    // Resource freigeben
    FreeAndNil(DatenStream);
  end;
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
Karsten

Registriert seit: 5. Sep 2003
56 Beiträge
 
Delphi 6 Personal
 
#7

Re: TStringList und Add-/InsertObject (Verständnisprobleme)

  Alt 6. Sep 2003, 19:37
Hallo,
also sind wir wieder beim record. Wobei, was bedeutet 'packed record' ?
Wenn ich mich bei den 'strings' auf eine Länge festlegen würde, kann man dann auf die Längenangabe als Datenwort (dwLen1 : DWORD verzichten ?

Was könnte man dann als Container-Komponente benutzen, die eine eine unbestimmte Anzahl an records beinhaltet.

Ziel ist es die Daten einmal komplett aus aus einer Datei auszulesen, zu bearbeiten und bei bedarf wieder zu speichern.

Wichtige Kriterien sind hier ein relatiev einfaches Einfügen (am Anfang, mitten drin und am Ende), Löschen und Ausleben von Daten des Typs TDaten.

Eine Idee meinerseits währe hier ein dynamisches Array vom Typ TDaten, wobei (soweit mein Wissensstand) man hier nach dem Ändern der Größe eines Arrays erst sämtliche Daten verschieben muß um einen neuen Datensatz in die Datenstruktur (nicht gerade am Ende) einzufügen.

Jetzt warte ich nur noch auf den Kommentar das es sich hier wieder auch nur um eine Pointerliste handelt ( ) die man nicht ohne weiteres in eine Datei speichern kann.

Falls doch nicht, welch Speichermethode währe hier zu wählen ? Da sich sämtliche Daten in der Container-Komponente befinden müsste eine bereits existierende Datei komplett überschrieben werden.

Gruß,
Karsten
  Mit Zitat antworten Zitat
Touchdown

Registriert seit: 17. Feb 2003
227 Beiträge
 
#8

Re: TStringList und Add-/InsertObject (Verständnisprobleme)

  Alt 6. Sep 2003, 20:20
@Karsten

Mit Objekten kann man wirklich alles lösen, niemand braucht sich mit Arrays ärgern.

Ich hab keine Ahnung was genau du machen willst, aber ich will dir mal eine Möglichkeit zeigen, ob du es nutzen kannst ist was anderes.

Du kannst dir eine Stringlist nehmen die Stringlisten verwaltet

Wenn du Spass dran hast kannst du auch eine Stringlist nehmen die wiederum Stinglisten verwaltet und auch die zweite Ebene Stringlisten könnten Stinglisten aufnehmen. Dies könnte man ohne ende so weiter treiben, alles möglich könnte aber jetzt zu weit führen

Die Stringlisten der zweiten Ebene könnte man alle extra in einer Datei speichern oder du machst eine große davon (könnte sich dann wohl sparen, aber machen könnte man es ohne weiteres).
function getallfornothing: TGoldesel;
begin
result := TGoldesel.create;
end;
  Mit Zitat antworten Zitat
Karsten

Registriert seit: 5. Sep 2003
56 Beiträge
 
Delphi 6 Personal
 
#9

Re: TStringList und Add-/InsertObject (Verständnisprobleme)

  Alt 6. Sep 2003, 21:10
Ich habe es auch vorher mit einer Stringliste realisiert. Wobei es hier wirklich nur eine Stringliste war und man beim ein- auslesen von
Daten immer die Startposition berechnen musste.

Der Grund mich für eine Stringliste zu entscheiden war das einfache speichern und lesen von Daten in einer Datei.

Code:
DatenListe.LoadFromFile(DateiName);

DatenListe.SaveToFile(DateiName);
Nur beim Auslesen oder Einfügen eines einzelnen Datensatzes muß man jedesmal die Startposition berechnen.

Desweiteren ist man hier auf den Datentypen 'String' beschränkt.

Im allgemeinen kann man mein Vorhaben mit einer Adress-Verwaltung vergleichen, wobei ich mir erst einmal Gedanken über die Datenstruktur mache um später nicht extrem komplexe Verfahren anwenden muß um irgendwelche Funktionen zu realisieren.

Am Anfang sind die Anforderungen wie folgt: simples
- auslesen (aller Daten) aus einer Datei
- schreiben (aller Daten) in eine Datei
- einfügen von Daten in die Datenstruktur
- löschen von Daten aus der Datenstruktur
- ändern von existierenden Daten in der Datenstruktur

was hoffentlich auch für die zukunft ausreicht.

Es geht hier lediglich um die Verwaltung von Daten eines einzelnen Typs. Bei der Datei handelt es sich um eine Typisierte Datei da die Daten immer vom Typ TDaten sind aber nicht umbedingt nur strings sein müssen.

Gruß,
Karsten
  Mit Zitat antworten Zitat
aogwaba

Registriert seit: 21. Aug 2003
16 Beiträge
 
#10

Re: TStringList und Add-/InsertObject (Verständnisprobleme)

  Alt 7. Sep 2003, 12:20
Dann benutz doch eine Klasse statt eines Records, und pack die ganze mechanik da hinein.
Um eine TList baust du eine Wrapper-Klasse, welche deine Daten verwaltet.
Ist ein bisschen mehr Schreibarbeit, aber wesentlich besser wartbar und
in ein paar Wochen noch nachvollziehbar....

Delphi-Quellcode:

unit Unit1;

interface

uses classes,SysUtils;
type

TDaten=class
constructor create (s:string;i:integer);
private
mytext:String;
myinteger:integer;
public
procedure readFromStream(aStream:tstream);
function writeToStream(aStream:tstream):integer;
end;

TDatenContainer=class
constructor create(fname:string);overload;
destructor destroy;override;
private
filename:string;
mylist:tlist;

public
procedure addItem(td:tdaten);
function getItemAt(i:integer):tdaten;

procedure readFromStream(aStream:Tstream);
procedure writeToStream(aStream:TStream);

end;

implementation

constructor TDaten.create(s:string;i:integer);
begin
mytext:=s;
myinteger:=i;
end;

procedure tDaten.readFromStream(aStream:Tstream);
var len:integer;
begin
  aStream.read(myinteger,sizeof(myinteger));
  aStream.read(len,sizeof(len));
  setLength(mytext,len);
  aStream.read(mytext[1],sizeof(mytext));
  //...
end;

function TDaten.writeToStream(aStream:tstream):integer;
var len:integer;
begin
  result:=aStream.position;
  aStream.write(myinteger,sizeof(myinteger));
  len:=length(mytext);
  aStream.write(len,sizeof(len));
  aStream.write(mytext[1],sizeof(mytext));
  //...
end;

constructor TDatenContainer.create(fname:string);
begin
  inherited create;
  filename:=fname;
  mylist:=tlist.create;
end;

procedure TDatenContainer.addItem(td:tdaten);
begin
  mylist.add(td);
end;

function TDatenContainer.getItemAt(i:integer):tdaten;
begin
result:=nil;
if i<mylist.count then result:=mylist.items[i];
end;

procedure TDatenContainer.readFromStream;
var mystream:tfileStream;
mydaten:tdaten;
i:integer;
begin
try
mystream:=tfilestream.create(filename,fmopenread);
mystream.read(i,sizeof(i));
for i:=0 to mylist.count-1 do
begin
  mydaten:=TDaten.create; //erst Instanz erzeugen, sorry!
  mydaten.readFromStream(mystream);
  Mylist.add(mydaten);
end;
finally
mystream.free;
end;
end;

procedure TDatenContainer.writeToStream;
var mystream:tfileStream;
mydaten:tdaten;
i,len:integer;
begin
try
mystream:=tfilestream.create(filename,fmopenread);
len:=mylist.count;
mystream.write(len,sizeof(len));
  for i:=0 to mylist.count-1 do
  begin
    mydaten:=mylist.items[i];
    mydaten.writeToStream(mystream);
  end;
finally
mystream.free;
end;
end;

destructor TDatenContainer.destroy;
begin
mylist.free;
inherited;
end;
  
end.
packed record= entfernt die padding(Füll-) bytes welche Delphi per default einfügt.

cu Waba
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:12 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz