Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Array of String in einer externen Datei speichern und laden (https://www.delphipraxis.net/206234-array-string-einer-externen-datei-speichern-und-laden.html)

Kegasetu 2. Dez 2020 09:08

Array of String in einer externen Datei speichern und laden
 
Hallo Zusammen. Dies wird wohl vorerst mein letzter Thread sein, ich stehe nun kurz vor Vollendung meines Programmes.

Zum Thema
Ich habe ein paar Str. Werte in einem Array gespeichert, welche in einer externen Datei gespeichert und im Anschluss wieder ausgelesen werden sollen. Mit einem Array of extended hat das wunderbar funktioniert:
Delphi-Quellcode:

procedure TForm2.Werte_speichernClick(Sender: TObject);
var fs:TFileStream;

    i : integer;

begin


  fs:=TFileStream.create(ExtractFilePath(ParamStr(0)) + 'Projekte\' + edit8.Text + '\Daten.dat',fmCreate);


try
 fs.write(db,sizeOf(db));
finally
 fs.free;
end;



procedure TForm2.Werte_ladenClick(Sender: TObject);
var fs:TFileStream;

begin
 if fileExists(ExtractFilePath(ParamStr(0)) + 'Projekte\' + edit8.Text + '\Daten.dat') then
begin
  fs:=TFileStream.create(ExtractFilePath(ParamStr(0)) + 'Projekte\' + edit8.Text + '\Daten.dat',fmOpenRead);
  try
    if fs.size >= sizeOf(db) then
    begin
     fs.read(db,sizeOf(db));
    end;
  finally
    fs.free;
  end;
end else showMessage('Werte nicht auffindbar');



end;
Den Code habe ich abgeschrieben. Mit einem String hat das ganze nicht funktioniert, dazu habe ich auch leider nichts hilfreiches gefunden.

Hier wird das Thema mal aufgegriffen, aber nicht weiter geklärt : https://www.delphipraxis.net/108616-...speichern.html

Um das Problem zu lösen, habe ich drei Ideen, 1. es analog versuchen, 2. die Werte in einer StringList speichern, da hier die Möglichkeit des Speicherns und Ladens schon gegeben ist. 3. die Strings Binär umwandeln

Leider hat mich keine Idee zum Erfolg gebracht, aber vielleicht hat hier jemand noch eine Vorschlag, den ich ausprobieren kann.

Vielen Dank für Unterstützung!

Klaus01 2. Dez 2020 09:16

AW: Array of String in einer externen Datei speichern und laden
 
.. eine Array of extended hat eine fest definierte Größe.
Ein Array of String hat keine fest definerte Größe, die Strings in dem Array können alle unterschiedlich lang sein.

Grüße
Klaus

DeddyH 2. Dez 2020 09:17

AW: Array of String in einer externen Datei speichern und laden
 
Im Gegensatz zu Extended hat ein String ja keine feste Größe, da musst Du schon etwas mehr Aufwand betreiben. So könntest Du je Array-Element zunächst dessen Länge (oder Bytegröße) in Deinen Stream schreiben und anschließend den eigentlichen String. Beim Lesen dann andersherum: zuerst die Länge auslesen, entsprechend Speicher reservieren und dann aus dem Stream lesen.

freimatz 2. Dez 2020 09:31

AW: Array of String in einer externen Datei speichern und laden
 
Hm, warum nicht in einer TStringList umfüllen?

Kegasetu 2. Dez 2020 09:33

AW: Array of String in einer externen Datei speichern und laden
 
Zitat:

Zitat von Klaus01 (Beitrag 1478372)
.. eine Array of extended hat eine fest definierte Größe.
Ein Array of String hat keine fest definerte Größe, die Strings in dem Array können alle unterschiedlich lang sein.

Grüße
Klaus

Es wäre doch bestimmt möglich Zeile für Zeile das Dokument mit den Inhalten des Arrays zu füllen?
Um das mal verbal zu beschreiben. Ich schreibe die Werte des Arrays in ein Dokument (Jedes Element eine Zeile). Dann lese ich jede Zeile bis zu einem Wert x aus und hänge alle Zeichen die kein '' sind aneinander und befülle anschließend wieder mein Array.

Blöde Frage, wie kann ich so etwas umsetzten?

Kegasetu 2. Dez 2020 09:34

AW: Array of String in einer externen Datei speichern und laden
 
Zitat:

Zitat von freimatz (Beitrag 1478375)
Hm, warum nicht in einer TStringList umfüllen?

Habe ich probiert, aber ich weiss nicht wie ich die Werte daraus wieder ins Array zurückbekomme.

runningsoft 2. Dez 2020 10:43

AW: Array of String in einer externen Datei speichern und laden
 
So würde ich den Inhalt der Stringlist ins Array wieder einlesen:

Delphi-Quellcode:
var
  Form1: TForm1;
  StrArr: array of string;
  MyStringList: TStringList;

procedure TForm1.Button1Click(Sender: TObject);
var I : integer;
begin
for I := 0 to MyStringList.Count - 1 do                  //Stringliste Zeilenweise abarbeiten
  begin
  SetLength(StrArr,Length(StrArr)+1);                    //Speicher reservieren
  StrArr[High(StrArr)] := MyStringList.Strings[I];       //Strings ins Array schreiben
  end;
MyStringList.Free;
//nur zur Kontrolle den Inhalt des StringArrays in einem Memo anzeigen
for I := 0 to High(StrArr) -1 do
  begin
  Memo1.Lines.Add(StrArr[I]);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
MyStringList := TStringList.Create;
MyStringList.LoadFromFile('test.bla');
end;
Steffen

Bbommel 2. Dez 2020 10:48

AW: Array of String in einer externen Datei speichern und laden
 
Falls du nicht den "Umweg" über die Stringliste gehen willst, kannst du dein Array auch direkt zeilenweise in eine Datei schreiben. Am komfortabelsten finde ich das mittels eines TStreamWriters, dort dann die Methode WriteLine.

Analog gibt es zum Lesen den TStreamReader mit der Methode ReadLine.

Vielleicht ist das ja auch noch mal eine Anregung. :-)

Uwe Raabe 2. Dez 2020 11:16

AW: Array of String in einer externen Datei speichern und laden
 
oder auch so:
Delphi-Quellcode:
var
  StrArr: TArray<string>;

begin
  StrArr := MyStringList.ToStringArray;

  Memo.Lines.Clear;
  Memo.Lines.AddStrings(StrArr);
end;

Kegasetu 2. Dez 2020 11:21

AW: Array of String in einer externen Datei speichern und laden
 
Zitat:

Zitat von runningsoft (Beitrag 1478382)
So würde ich den Inhalt der Stringlist ins Array wieder einlesen:

Delphi-Quellcode:
var
  Form1: TForm1;
  StrArr: array of string;
  MyStringList: TStringList;

procedure TForm1.Button1Click(Sender: TObject);
var I : integer;
begin
for I := 0 to MyStringList.Count - 1 do                  //Stringliste Zeilenweise abarbeiten
  begin
  SetLength(StrArr,Length(StrArr)+1);                    //Speicher reservieren
  StrArr[High(StrArr)] := MyStringList.Strings[I];       //Strings ins Array schreiben
  end;
MyStringList.Free;
//nur zur Kontrolle den Inhalt des StringArrays in einem Memo anzeigen
for I := 0 to High(StrArr) -1 do
  begin
  Memo1.Lines.Add(StrArr[I]);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
MyStringList := TStringList.Create;
MyStringList.LoadFromFile('test.bla');
end;
Steffen

Danke für den Code, aber irgendwie blicke ich noch nicht so ganz durch. Das Erste was ich mache, ist die Stringlist zu füllen. Das habe ich so gemacht:
Delphi-Quellcode:

procedure TForm2.Werte_speichernClick(Sender: TObject);
var fs,ds:TFileStream;

    i : integer;

    bsb : TStringList;

begin

  bsb.Create;

try

  for i := 0 to 519 do
    bsb.Add(bzb[i]);


end;
Hier bekomme ich immer die Meldung, dass eine Zugriffverletzung bei Adresse ... vorliegt.
bzb ist bereits voll definiert, also von 0 bis 519, und zwar mit ''

DeddyH 2. Dez 2020 11:22

AW: Array of String in einer externen Datei speichern und laden
 
Delphi-Quellcode:
 bsb := TStringList.Create;

Klaus01 2. Dez 2020 11:22

AW: Array of String in einer externen Datei speichern und laden
 
Delphi-Quellcode:
bsb := TstringList.Create;

Kegasetu 2. Dez 2020 11:42

AW: Array of String in einer externen Datei speichern und laden
 
.... Danke

Kegasetu 2. Dez 2020 12:02

AW: Array of String in einer externen Datei speichern und laden
 
Habe es hinbekommen. Vielen Dank euch!

runningsoft 2. Dez 2020 12:04

AW: Array of String in einer externen Datei speichern und laden
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1478389)
oder auch so:
Delphi-Quellcode:
var
  StrArr: TArray<string>;

begin
  StrArr := MyStringList.ToStringArray;

  Memo.Lines.Clear;
  Memo.Lines.AddStrings(StrArr);
end;

Das ist natürlich um einiges kürzer. Wieder was gelernt :thumb:

Mavarik 3. Dez 2020 15:09

AW: Array of String in einer externen Datei speichern und laden
 
Hmm...

Schneller geht immer, oder?

Was ist wenn die Datei mit D6 oder D2007 erzeugt wurde und in XE eingelesen werden muss...

32Bit Schreiben, 64 Bit Lesen hab ich nicht berücksichtig. Ginge aber auch indem man aus Integer Int32 macht..

Wir gehen mal davon aus, dass die Datei nicht 2TB groß ist, oder defekt... (Könnte man natürlich alles abfangen)

Bisschen "Schön-Wetter-Code" gefällig?

Delphi-Quellcode:
program Project378;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils
, System.Classes
;

  Procedure Schreibe(Const aBzB : TArray<String>);
  var
    CharSize : byte;
    Anz,
    L,
    I       : Integer;
    MS      : TMemoryStream;
    P       : Pointer;
    PP      : NativeUInt absolute P;
  begin
    MS := TMemoryStream.Create;
    try
      Anz     := Length(aBzB);
      CharSize := Sizeof(Char);

      L := 0;

      for i:=0 to Anz-1 do
        inc(L,Length(aBzB[i]) * CharSize);

     MS.SetSize(Sizeof(Anz)+1+Anz*Sizeof(Integer)+L);
     MS.Position := 0;

     P := MS.Memory;

     Move(Anz,P^,Sizeof(Anz));
     inc(PP,Sizeof(Anz));

     Move(CharSize,P^,1);
     inc(PP);

     for i:=0 to high(aBZB) do
       begin
         L := Length(aBzB[i]);
         Move(L,P^,Sizeof(L));
         inc(PP,Sizeof(L));
         L := L * CharSize;
         Move(aBzB[i][1],P^,L);
         inc(PP,L);
       end;

     MS.SaveToFile('Daten.Dat');
    finally
      MS.Free;
    end;
  end;

  {.$DEFINE CanDoAnsiRead}

  Procedure Lese(Var aBzB : TArray<String>);
  var
    CharSize : byte;
    Anz,
    L,
    I  : Integer;
    MS : TMemoryStream;
    Len : TArray<Word>;
    P  : Pointer;
    PP : NativeUInt absolute P;

    {$IFDEF CanDoAnsiRead}
    S       : AnsiString;
    AnsiRead : boolean;
    {$ENDIF}
  begin
    {$IFDEF CanDoAnsiRead}
    AnsiRead := false;
    {$ENDIF}

    MS := TMemoryStream.Create;
    try
      MS.LoadFromFile('Daten.dat');
      MS.Position := 0;
      P := MS.Memory;
      Move(P^,Anz,Sizeof(Anz));
      Inc(PP,Sizeof(Anz));

      Move(P^,CharSize,1);
      inc(PP);

      if (CharSize <> Sizeof(Char)) then
        {$IFDEF CanDoAnsiRead}
        if (CharSize = 1)
          then AnsiRead := true
          else {$ENDIF}
               raise Exception.Create('Daten wurden mit eine Unicode Delphi Version erzeugt'); // Könnte man ggf. in Widestrings einlesen...

      Setlength(aBzB,Anz);
      for i:=0 to Anz-1 do
        begin
          Move(P^,L,Sizeof(L));
          inc(PP,Sizeof(L));

          {$IFDEF CanDoAnsiRead}
          if AnsiRead
            then begin
                   Setlength(S,L);
                   Move(P^,S[1],L);
                   inc(PP,L);
                   aBzB[i] := S; // UTF8?
                 end
            else begin {$ENDIF}
                   Setlength(aBzB[i],L);
                   Move(P^,aBzB[i][1],L*CharSize);
                   inc(PP,L*CharSize);
{$IFDEF CanDoAnsiRead} end; {$ENDIF}
        end;
    finally
      MS.Free;
    end;
  end;

Var
  BzBSource,
  BzBDest   : TArray<String>;
  I         : Integer;
begin
  try
    BzBSource := ['Frank','Peter','Klaus','Sebastian'];
    Schreibe(BzBSource);
    Lese(BzBDest);

    if Length(BzBDest) <> Length(BzBSource) then
      Raise Exception.Create('Source <> Dest');

    for i:=0 to high(BzBSource) do
      if BzBSource[i] <> BzBDest[i] then
         Raise Exception.Create('Daten unterschiedlich!');

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
Oder so...

Mavarik :coder:

himitsu 3. Dez 2020 15:14

AW: Array of String in einer externen Datei speichern und laden
 
Bei TArray<string> ein Delphi-Referenz durchsuchenTFile.ReadAllLines und Delphi-Referenz durchsuchenTFile.WriteAllLines :angle:


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