Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi TStringList in Datei/File speichern und laden (https://www.delphipraxis.net/200513-tstringlist-datei-file-speichern-und-laden.html)

Pytroxis 27. Apr 2019 09:20

Delphi-Version: 10.2 Tokyo

TStringList in Datei/File speichern und laden
 
Guten Morgen,

prinzipiell ist mir bekannt wie ich eine TStringList speichern und laden könnte, allerdings sieht meine Situation wie folgt aus:
Bei der Variable handelt es sich um ein dynamischen Array, demnach ist das abspeichern erschwert und das laden erst recht.
In meinem Fall nutze ich den
Delphi-Quellcode:
SaveDialog
, sowie den
Delphi-Quellcode:
OpenDialog
.
Wie kann ich den Array am geschicktesten abspeichern und laden?
Beim speichern würde ich eine Schleife nehmen, allerdings habe ich beim laden keinen Plan, da ja die Länge des Arrays, beim laden, unbekannt ist :pale:

Bernhard Geyer 27. Apr 2019 09:32

AW: TStringList in Datei/File speichern und laden
 
Lade es in eine Stringliste und kopiere es dann mittles ToStringArray in ein TArray<String>

Pytroxis 27. Apr 2019 09:39

AW: TStringList in Datei/File speichern und laden
 
Zitat:

Zitat von Bernhard Geyer (Beitrag 1431117)
Lade es in eine Stringliste und kopiere es dann mittles ToStringArray in ein TArray<String>

Kannst du es mir vielleicht etwas genauer erklären? Aus deinem Satz werde ich leider nicht ganz Schlau :S
Beim speichern habe ich auch noch meine Probleme, ist es möglich den gesamten Array in eine Datei zu speichern?

Bernhard Geyer 27. Apr 2019 09:44

AW: TStringList in Datei/File speichern und laden
 
Welche Art von Zeichen beinhaltet dein Array? String es Strings oder "beliebige Binärdaten" (bin jetzt implizit von Strings ausgegangen)?

Uwe Raabe 27. Apr 2019 10:55

AW: TStringList in Datei/File speichern und laden
 
Zitat:

Zitat von Bernhard Geyer (Beitrag 1431119)
(bin jetzt implizit von Strings ausgegangen)?

Der Thread-Titel lässt ja auch kaum eine andere Annahme zu. Wenn es also wirklich nicht um ein TArray<string> geht, dann sollte man den besser ändern.

Pytroxis 27. Apr 2019 11:42

AW: TStringList in Datei/File speichern und laden
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1431121)
Der Thread-Titel lässt ja auch kaum eine andere Annahme zu. Wenn es also wirklich nicht um ein TArray<string> geht, dann sollte man den besser ändern.

Zitat:

Zitat von Bernhard Geyer (Beitrag 1431119)
Welche Art von Zeichen beinhaltet dein Array? String es Strings oder "beliebige Binärdaten" (bin jetzt implizit von Strings ausgegangen)?

Mein Fehler, habe mich hierbei nicht korrekt ausgedrückt.
Es handelt sich um einen Array vom Typ StringList. Jeder Index repräsentiert einen Datensatz (Hier "Integer" einer ListBox).
Demnach ist jeder Array die Items einer ListBox (-> wird für ein dynamisches System benötigt).
Ich möchte nun den Array bzw. die Datensätze in einer Datei speichern und laden, sodass der Benutzer jeder Zeit damit arbeiten kann.

peterbelow 27. Apr 2019 11:44

AW: TStringList in Datei/File speichern und laden
 
Zitat:

Zitat von Pytroxis (Beitrag 1431116)
Guten Morgen,

prinzipiell ist mir bekannt wie ich eine TStringList speichern und laden könnte, allerdings sieht meine Situation wie folgt aus:
Bei der Variable handelt es sich um ein dynamischen Array, demnach ist das abspeichern erschwert und das laden erst recht.
In meinem Fall nutze ich den
Delphi-Quellcode:
SaveDialog
, sowie den
Delphi-Quellcode:
OpenDialog
.
Wie kann ich den Array am geschicktesten abspeichern und laden?
Beim speichern würde ich eine Schleife nehmen, allerdings habe ich beim laden keinen Plan, da ja die Länge des Arrays, beim laden, unbekannt ist :pale:

Ist es notwendig, das die erzeugte Datei wirklich Text ist, oder kann es auch ein Binärformat sein? Wenn das geht kannst Du die TReader- und TWriter-Klassen verwenden:

Delphi-Quellcode:
type
  TStringArrayFiler = class(TObject)
  public
    class procedure LoadArray(var aArray: TArray<string>; const aFilename: string);
    class procedure SaveArray(const aArray: array of string; const aFilename:
        string);

  end;

class procedure TStringArrayFiler.LoadArray(var aArray: TArray<string>; const
    aFilename: string);
var
  LStream: TFilestream;
  LReader: TReader;
  I: Integer;
begin
  LStream := TFilestream.Create(aFilename, fmOpenRead or fmShareDenyWrite);
  try
    LReader := TReader.Create(LStream, 4096);
    try
      SetLength(aArray, LReader.ReadInteger);
      for I := Low(aArray) to High(aArray) do
        aArray[I] := LReader.ReadString;
    finally
      LReader.Free;
    end;
  finally
    LStream.Free;
  end;
end;

class procedure TStringArrayFiler.SaveArray(const aArray: array of string;
    const aFilename: string);
var
  LStream: TFilestream;
  LWriter: TWriter;
  I: Integer;
begin
  LStream := TFilestream.Create(aFilename, fmCreate);
  try
    LWriter := TWriter.Create(LStream, 4096);
    try
      LWriter.WriteInteger(Length(aArray));
      for I := Low(aArray) to High(aArray) do
        LWriter.WriteString(aArray[I]);
    finally
      LWriter.Free;
    end;
  finally
    LStream.Free;
  end;
end;

p80286 27. Apr 2019 11:54

AW: TStringList in Datei/File speichern und laden
 
Noch mal nachgefragt:
Delphi-Quellcode:
var
  myarr : array[0..n] of tstringlist;
ist das so korrekt?

Und das mochtest Du in einem Rutsch speichern?

Delphi-Quellcode:
myarr.savetoFile();
Gruß
K-H

Uwe Raabe 27. Apr 2019 12:07

AW: TStringList in Datei/File speichern und laden
 
Zitat:

Zitat von p80286 (Beitrag 1431126)
Noch mal nachgefragt:
Delphi-Quellcode:
var
  myarr : array[0..n] of tstringlist;
ist das so korrekt?

Vermutlich nicht so ganz:

Zitat:

Zitat von Pytroxis (Beitrag 1431116)
Bei der Variable handelt es sich um ein dynamischen Array,


Pytroxis 27. Apr 2019 16:31

AW: TStringList in Datei/File speichern und laden
 
Zitat:

Zitat von peterbelow (Beitrag 1431125)
Zitat:

Zitat von Pytroxis (Beitrag 1431116)
Guten Morgen,

prinzipiell ist mir bekannt wie ich eine TStringList speichern und laden könnte, allerdings sieht meine Situation wie folgt aus:
Bei der Variable handelt es sich um ein dynamischen Array, demnach ist das abspeichern erschwert und das laden erst recht.
In meinem Fall nutze ich den
Delphi-Quellcode:
SaveDialog
, sowie den
Delphi-Quellcode:
OpenDialog
.
Wie kann ich den Array am geschicktesten abspeichern und laden?
Beim speichern würde ich eine Schleife nehmen, allerdings habe ich beim laden keinen Plan, da ja die Länge des Arrays, beim laden, unbekannt ist :pale:

Ist es notwendig, das die erzeugte Datei wirklich Text ist, oder kann es auch ein Binärformat sein? Wenn das geht kannst Du die TReader- und TWriter-Klassen verwenden:

Delphi-Quellcode:
type
  TStringArrayFiler = class(TObject)
  public
    class procedure LoadArray(var aArray: TArray<string>; const aFilename: string);
    class procedure SaveArray(const aArray: array of string; const aFilename:
        string);

  end;

class procedure TStringArrayFiler.LoadArray(var aArray: TArray<string>; const
    aFilename: string);
var
  LStream: TFilestream;
  LReader: TReader;
  I: Integer;
begin
  LStream := TFilestream.Create(aFilename, fmOpenRead or fmShareDenyWrite);
  try
    LReader := TReader.Create(LStream, 4096);
    try
      SetLength(aArray, LReader.ReadInteger);
      for I := Low(aArray) to High(aArray) do
        aArray[I] := LReader.ReadString;
    finally
      LReader.Free;
    end;
  finally
    LStream.Free;
  end;
end;

class procedure TStringArrayFiler.SaveArray(const aArray: array of string;
    const aFilename: string);
var
  LStream: TFilestream;
  LWriter: TWriter;
  I: Integer;
begin
  LStream := TFilestream.Create(aFilename, fmCreate);
  try
    LWriter := TWriter.Create(LStream, 4096);
    try
      LWriter.WriteInteger(Length(aArray));
      for I := Low(aArray) to High(aArray) do
        LWriter.WriteString(aArray[I]);
    finally
      LWriter.Free;
    end;
  finally
    LStream.Free;
  end;
end;

Vielen Dank schon einmal!
Aber gibt es vielleicht eine kompaktere Version bzw. eine kompaktere Möglichkeit? :)


Zitat:

Zitat von Uwe Raabe (Beitrag 1431129)
Zitat:

Zitat von p80286 (Beitrag 1431126)
Noch mal nachgefragt:
Delphi-Quellcode:
var
  myarr : array[0..n] of tstringlist;
ist das so korrekt?

Vermutlich nicht so ganz:

Zitat:

Zitat von Pytroxis (Beitrag 1431116)
Bei der Variable handelt es sich um ein dynamischen Array,


Jep du liegst natürlich richtig, bei einem dynamischen Array ist das leider nicht möglich :pale:

hoika 27. Apr 2019 16:53

AW: TStringList in Datei/File speichern und laden
 
Hallo,
erstmal eine funktionierenden Version machen.
Hör bitte auf mit diesem ständigen "kompakt"... :)

p80286 27. Apr 2019 17:14

AW: TStringList in Datei/File speichern und laden
 
Die Frage ist: was ist "kompakt"?
Irgendwie werde ich das Gefühl nicht los, daß hier ein Format wie .INI oder .XML angebrachter wäre.
Oder vielleicht die Ablage in einer DB?

eine klitzekleine Änderung in der Textdatei und schon hat man unerklärliches Datenhack.

Gruß
K-H

Pytroxis 27. Apr 2019 17:28

AW: TStringList in Datei/File speichern und laden
 
Zitat:

Zitat von hoika (Beitrag 1431138)
Hallo,
erstmal eine funktionierenden Version machen.
Hör bitte auf mit diesem ständigen "kompakt"... :)

Kompakt ist in meinem Fall aber wichtig, muss wie gesagt den gesamten Code + Interface, etc. auf ca. 12 Seiten erklären. Jeder Schnipsel Code denn ich mehr benötige benötigt auch mehr Erklärung und da der Raum bzw. die Seitenanzahl limitiert ist muss ich halt möglichst kompakt und kurz schreiben.


Zitat:

Zitat von p80286 (Beitrag 1431139)
Die Frage ist: was ist "kompakt"?
Irgendwie werde ich das Gefühl nicht los, daß hier ein Format wie .INI oder .XML angebrachter wäre.
Oder vielleicht die Ablage in einer DB?

eine klitzekleine Änderung in der Textdatei und schon hat man unerklärliches Datenhack.

Gruß
K-H

Prinzipiell keine schlechte Idee, allerdings ist dieses "Projekt" ein Teil meiner Facharbeit.
Letztlich wird niemand in den Textdateien rumpfuschen. Hatte ebenfalls an eine Ini-Gedacht, allerdings wollte ich mal erfragen ob es auch alternativen dazu gibt.

Dalai 27. Apr 2019 19:24

AW: TStringList in Datei/File speichern und laden
 
Mal eine ganz praktische Überlegung: Erstmal solltest du dir Gedanken darüber machen, ob du alles in einer Datei ablegen willst oder jede Stringliste in eine eigene Datei. Das ist übrigens völlig unabhängig davon, ob dynamisches Array oder nicht.

Anders ausgedrückt: Wie du ja selbst schon bemerkt hast, gibt es die Methode TStringList.SaveToFile, die einen Dateinamen als Parameter bekommt. Du hast aber ein
Delphi-Quellcode:
Array of TStringList
. Willst du also für jede deiner Stringlisten eine separate Datei anlegen? Diese Überlegung ist ja auch fürs Laden mit LoadFromFile relevant.

Wenn du alles in eine Datei packen kannst/willst, musst du eine Gesamt-Stringlist erzeugen, diese in einer Schleife befüllen (aus den Listen im Array) und dann das Ergebnis abspeichern. Wenn jede Liste eine eigene Datei bekommen soll, musst du dir Gedanken darüber machen, wie du die Dateinamen zusammenbaust, so dass sie später auch wieder eingelesen werden können (sofern nötig).

Grüße
Dalai

Pytroxis 27. Apr 2019 20:06

AW: TStringList in Datei/File speichern und laden
 
Zitat:

Zitat von Dalai (Beitrag 1431148)
Mal eine ganz praktische Überlegung: Erstmal solltest du dir Gedanken darüber machen, ob du alles in einer Datei ablegen willst oder jede Stringliste in eine eigene Datei. Das ist übrigens völlig unabhängig davon, ob dynamisches Array oder nicht.

Am besten alles in einer Datei, denke, dass so auch das Laden einfacher ist.

Zitat:

Zitat von Dalai (Beitrag 1431148)
Anders ausgedrückt: Wie du ja selbst schon bemerkt hast, gibt es die Methode TStringList.SaveToFile, die einen Dateinamen als Parameter bekommt. Du hast aber ein
Delphi-Quellcode:
Array of TStringList
. Willst du also für jede deiner Stringlisten eine separate Datei anlegen? Diese Überlegung ist ja auch fürs Laden mit LoadFromFile relevant.
Wenn du alles in eine Datei packen kannst/willst, musst du eine Gesamt-Stringlist erzeugen, diese in einer Schleife befüllen (aus den Listen im Array) und dann das Ergebnis abspeichern. Wenn jede Liste eine eigene Datei bekommen soll, musst du dir Gedanken darüber machen, wie du die Dateinamen zusammenbaust, so dass sie später auch wieder eingelesen werden können (sofern nötig).

Bin gerade leider unterwegs und demnach nicht am Rechner. Ist es überhaupt möglich ein
Delphi-Quellcode:
array of TStringList
einer
Delphi-Quellcode:
TStringList
zuzuweisen, sodass man
Delphi-Quellcode:
TStringList.SaveToFile
nutzen kann? Sprich:
Delphi-Quellcode:
var test : TStringList;
test2 : Array of TStringLIst;
...
for i:= 0 to Length(test2) do
 test[i] := test2[i];
Oder meinst du es anders?

Dalai 27. Apr 2019 20:52

AW: TStringList in Datei/File speichern und laden
 
Du musst die Gesamt-Stringlist erzeugen, dann das Array durchlaufen und die Einzellisten mit AddStrings in die Gesamt-Stringlist packen. Etwa so:
Delphi-Quellcode:
var
    ar: array of TStringList;

procedure blub;
var sl: TStringList;
    i: integer;
begin
    sl:= TStringList.Create;
    try
        for i:= Low(ar) to High(ar) do begin
           sl.AddStrings(ar[i]);
        end;
        sl.SaveToFile(...);
    finally
        sl.Free;
    end;
end;
Beachte aber, dass ein nachträgliches Auseinandernehmen nicht möglich ist, d.h. ein Einlesen geht nur komplett als einzelne Stringliste, es sei denn, du weiß, wie weit du lesen müsstest, aber das ist auch nicht wirklich zuverlässig.

Grüße
Dalai

Pytroxis 27. Apr 2019 21:31

AW: TStringList in Datei/File speichern und laden
 
Zitat:

Zitat von Dalai (Beitrag 1431158)
Du musst die Gesamt-Stringlist erzeugen, dann das Array durchlaufen und die Einzellisten mit AddStrings in die Gesamt-Stringlist packen. Etwa so:
Delphi-Quellcode:
var
    ar: array of TStringList;

procedure blub;
var sl: TStringList;
    i: integer;
begin
    sl:= TStringList.Create;
    try
        for i:= Low(ar) to High(ar) do begin
           sl.AddStrings(ar[i]);
        end;
        sl.SaveToFile(...);
    finally
        sl.Free;
    end;
end;
Beachte aber, dass ein nachträgliches Auseinandernehmen nicht möglich ist, d.h. ein Einlesen geht nur komplett als einzelne Stringliste, es sei denn, du weiß, wie weit du lesen müsstest, aber das ist auch nicht wirklich zuverlässig.

Grüße
Dalai

Danke für den Tipp bzw. die Hilfe!
Aber das laden in einzelne Teile ist leider wichtig, werde es dann mal mit Ini-Files probieren, darüber müsste es eigentlich gehen.
Vielen Dank an alle die mir geholfen haben! :)

striderx 27. Apr 2019 21:47

AW: TStringList in Datei/File speichern und laden
 
Warum fügst du nicht beim Zusammenbauen der Gesamt-Stringlist vor jeder Teilliste jeweils einen Markierungsstring ein, anhand dessen du später nach dem laden die Gesamt-Liste wieder auseinander nehmen kannst?

Luckie 27. Apr 2019 22:40

AW: TStringList in Datei/File speichern und laden
 
Du unterliegst einem Trugschluss. Kompakter Code ist unverständlicher und bedarf mehr Erklärung. Guter, verständliche, selbsterklärender Code benötigt weniger Erklärung. Benenne Variablen und Routinen "sprechend" und der Code erklärt sich fast von selbst.

samso 28. Apr 2019 07:43

AW: TStringList in Datei/File speichern und laden
 
Mein Vorschlag:

Delphi-Quellcode:
var
    ar: array of TStringList;

procedure save(const Filename: String);
var
  sl: TStringList;
  i: integer;
begin
    sl:= TStringList.Create;
    try
      for i:= Low(ar) to High(ar) do begin
         sl.Add(ar[i].Commatext);
      end;
      sl.SaveToFile(Filename);
    finally
        sl.Free;
    end;
end;
procedure load(const Filename: String);
var
  sl: TStringList;
  i: integer;
begin
  assert(Length(ar)=0);
    sl:= TStringList.Create;
    try
      s1.LoadFromFile(Filename);
      SetLength(ar, s1.Count);
      for i:= 0 to s1.Count-1 do begin
        ar[i] := TStringList.Create;
        ar[i].Commatext := s1[i]);
      end;
    finally
      sl.Free;
    end;
end;

Pytroxis 28. Apr 2019 09:35

AW: TStringList in Datei/File speichern und laden
 
Zitat:

Zitat von Luckie (Beitrag 1431164)
Du unterliegst einem Trugschluss. Kompakter Code ist unverständlicher und bedarf mehr Erklärung. Guter, verständliche, selbsterklärender Code benötigt weniger Erklärung. Benenne Variablen und Routinen "sprechend" und der Code erklärt sich fast von selbst.

Den Gedanken hatte ich auch schon aber letztlich hast du wohl recht :)


Zitat:

Zitat von samso (Beitrag 1431189)
Mein Vorschlag:

Vielen Dank, werde das später auch mal testen.


Dann frage ich noch mal so:
Welche Möglichkeit sollte ich nun nutzen? Sollte ich eher über Ini-Files gehen oder doch lieber über
Delphi-Quellcode:
SaveToFile
gehen?
Gibt es bei den beiden Methoden irgendwelche Vor- bzw. Nachteile?


Edit:
Was macht Eigentlich
Delphi-Quellcode:
assert()
? Habe es schon mehrfach gesehen aber bisher noch keine Erklärung gesehen :O

striderx 28. Apr 2019 09:48

AW: TStringList in Datei/File speichern und laden
 
Zitat:

Zitat von Pytroxis (Beitrag 1431191)
Welche Möglichkeit sollte ich nun nutzen? Sollte ich eher über Ini-Files gehen oder doch lieber über
Delphi-Quellcode:
SaveToFile
gehen?

Ini-Files sind dazu da, um Initialisierung-Information zu speichern und sollten nicht für die Datenhaltung mißbraucht werden. Ich würde mir die Gesamt-Liste mit Trenn-Strings zusammenbastel, mit SaveToFile in eine Datei speichern und dann nach dem Laden sequentiell durchgegehen und anhand der Trennstrings wieder zerlegen.

striderx 28. Apr 2019 09:52

AW: TStringList in Datei/File speichern und laden
 
Zitat:

Zitat von Pytroxis (Beitrag 1431191)
Was macht Eigentlich
Delphi-Quellcode:
assert()
? Habe es schon mehrfach gesehen aber bisher noch keine Erklärung gesehen :O

Du weißt schon, dass es in Delphi eine Hilfefunktion gibt?

Pytroxis 28. Apr 2019 12:05

AW: TStringList in Datei/File speichern und laden
 
Zitat:

Zitat von striderx (Beitrag 1431196)
Ich würde mir die Gesamt-Liste mit Trenn-Strings zusammenbastel, mit SaveToFile in eine Datei speichern und dann nach dem Laden sequentiell durchgegehen und anhand der Trennstrings wieder zerlegen.

Dann mache ich es auf Basis des Codes eines Vorredners :D

Rudy Velthuis 28. Apr 2019 13:07

AW: TStringList in Datei/File speichern und laden
 
[/QUOTE]Hatte ebenfalls an eine Ini-Gedacht, allerdings wollte ich mal erfragen ob es auch alternativen dazu gibt.[/QUOTE]

JSON. Kan man besser "verschachteln" (also array of array of string) als Ini-Dateien und ist schlanker als XML.

Pytroxis 28. Apr 2019 14:07

AW: TStringList in Datei/File speichern und laden
 
Zitat:

Zitat von Rudy Velthuis (Beitrag 1431212)
JSON. Kan man besser "verschachteln" (also array of array of string) als Ini-Dateien und ist schlanker als XML.

Ich habe mir das gerade mal angeguckt. Wäre es ein Eindimensionaler Array, wäre es kein Problem aber so wie ich das sehe wird es mit einem Mehrdimensionalen Array sehr viel Schreibarbeit, außerdem sieht es danach sehr kompliziert und unverständlich aus (habe online nur Lösung für eindimensionale Arrays gesehen und beim selbst schreiben ist mir aufgefallen, wie umfangreich und unverständlich es geworden ist).


Zitat:

Zitat von Luckie (Beitrag 1431164)
Du unterliegst einem Trugschluss. Kompakter Code ist unverständlicher und bedarf mehr Erklärung. Guter, verständliche, selbsterklärender Code benötigt weniger Erklärung. Benenne Variablen und Routinen "sprechend" und der Code erklärt sich fast von selbst.

Habe mal dein "Kommentar" bzw. deinen Rat war genommen.
Nutze jetzt mehr Variablen um Teile/Rechnungen, welche ich öfters verwende, daran zu speichern. Somit übergebe ich den Funktionen nur noch diese Variablen, dadurch ist es um einiges übersichtlicher geworden :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:27 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