Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   TDictionary speichern (https://www.delphipraxis.net/199845-tdictionary-speichern.html)

skoschke 25. Feb 2019 12:20

TDictionary speichern
 
Hallo,

immer mehr liebe ich die Vorzüge des TDictionary ;-)

Nun möchte ich ein solches (am besten in einen Stream) speichern um es anderweitig wiederverwenden zu können.

Ich suche seit etlicher Zeit, aber so richtig den Durchbruch habe ich nicht geschafft, es sei denn, ich bastle mir da komplett etwas eigenes, was die Wertpaare speichert, aber da muss es doch eigentlich etwas "fertiges" geben?

Hat jemand den entscheidenden Tip für mich?
Es geht um ein primitives TDictionary<string, string>;

Ciao
Stefan

TiGü 25. Feb 2019 12:30

AW: TDictionary speichern
 
Delphi-Quellcode:
program Project1;

{$APPTYPE CONSOLE}

{$R *.res}


uses
  System.SysUtils,
  System.Classes,
  System.Generics.Collections;

procedure Main;
var
  KoschkesStrings: TDictionary<string, string>;
  I: Integer;
  Stream: TStream;
  Pair: TPair<string, string>;
  KoschkesData: string;
begin
  KoschkesStrings := TDictionary<string, string>.Create;
  try
    for I := 1 to 100 do
    begin
      KoschkesStrings.Add(I.ToString, (I * I).ToString);
    end;

    KoschkesData := '';
    for Pair in KoschkesStrings do
    begin
      KoschkesData := KoschkesData + Pair.Key + ':' + Pair.Value + sLineBreak;
    end;

    Stream := TStringStream.Create(KoschkesData);
    try
      Writeln((Stream as TStringStream).Datastring);
    finally
      Stream.Free;
    end;
  finally
    KoschkesStrings.Free;
  end;
end;

begin
  try
    Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

skoschke 25. Feb 2019 12:50

AW: TDictionary speichern
 
danke, aber das geht in die Richtung, an die ich beim "selber basteln" dachte...

Denn zurück aus Stream ins TDictionary müssen ja die Keys anhand des ':' wieder von den Values getrennt werden und die Pärchen anhand des sLinebreak...

Dumm, wenn dann in den Values auch mal ein sLinebreak vorkommt!

Gibt es da wirklich nichts fertiges?

Ciao
Stefan

Klaus01 25. Feb 2019 13:01

AW: TDictionary speichern
 
.. als Trenner kannst Du doch nehmen was Du willst.

Grüße
Klaus

haentschman 25. Feb 2019 13:09

AW: TDictionary speichern
 
[Ohne Gewähr]
Aus dem Dictionary einen JSON String machen, speichern, einlesen, wieder ein TDictionary draus machen.

Lesen u.a.:
Marshalling: https://www.delphipraxis.net/dp_refe...20&lib=embtx10
https://www.delphipraxis.net/182309-...n-strings.html
https://community.idera.com/develope...e-line-of-code

Rollo62 25. Feb 2019 13:33

AW: TDictionary speichern
 
Ja, ein JSON-Array fände ich auch super.

Ansonsten könntest du die Strings in TBytes umwandeln, und per ByteToHEX-Encoding 1:1 speichern, oder mit Base64 kodieren, wenn dir das sicherer erscheint.
Ich denke aber das es womöglich den Aufwand nicht Wert ist.
Deshalb +1 für JSON :thumb:

Schokohase 25. Feb 2019 13:58

AW: TDictionary speichern
 
Zitat:

Zitat von Rollo62 (Beitrag 1426384)
Ja, ein JSON-Array fände ich auch super.

Ein JSON-Object, denn das verhält sich schon wie ein Dictionary, denn die Eigenschaften in einem JSON-Object müssen eindeutig sein.

TiGü 25. Feb 2019 14:03

AW: TDictionary speichern
 
Zitat:

Zitat von Rollo62 (Beitrag 1426384)
Ja, ein JSON-Array fände ich auch super.

Ansonsten könntest du die Strings in TBytes umwandeln, und per ByteToHEX-Encoding 1:1 speichern, oder mit Base64 kodieren, wenn dir das sicherer erscheint.
Ich denke aber das es womöglich den Aufwand nicht Wert ist.
Deshalb +1 für JSON :thumb:

Oder: http://docwiki.embarcadero.com/RADStudio/Rio/en/BSON

Uwe Raabe 25. Feb 2019 14:10

AW: TDictionary speichern
 
Fertig gibt es da wohl noch nichts, aber man kann das mit überschaubarem Aufwand selbst machen:
Delphi-Quellcode:
procedure Test;
type
  TDict = TDictionary<string,string>;
  TDictPair = TPair<string,string>;
  TDictArray = TArray<TDictPair>;
var
  arr: TDictArray;
  dict: TDict;
  pair: TDictPair;
  theJSONString: string;
  ser: TJsonSerializer;
begin
  dict := TDict.Create;
  try
    dict.Add('Hallo', 'Welt');
    dict.Add('RAD', 'Studio');
    arr := dict.ToArray;
    ser := TJsonSerializer.Create;
    try
      theJSONString := ser.Serialize(arr);
    finally
      ser.Free;
    end;
  finally
    dict.Free;
  end;

  ser := TJsonSerializer.Create;
  try
    arr := ser.Deserialize<TDictArray>(theJSONString);
  finally
    ser.Free;
  end;
  dict := TDict.Create;
  try
    for pair in arr do begin
      dict.Add(pair.Key, pair.Value);
    end;

    Assert(dict['Hallo'] = 'Welt');
    Assert(dict['RAD'] = 'Studio');
  finally
    dict.Free;
  end;
end;

skoschke 25. Feb 2019 14:30

AW: TDictionary speichern
 
Danke,

das wollte ich eben mal ausprobieren, aber das scheint es in Berlin 10.1 noch nicht zu geben :-(

Ciao
Stefan

TiGü 25. Feb 2019 15:44

AW: TDictionary speichern
 
Ja, das kam erst in Tokyo hinzu.
https://community.embarcadero.com/de...son-converters

Dann nimm doch meine zu Fuss-Variante?!

Rollo62 25. Feb 2019 18:49

AW: TDictionary speichern
 
Hallo Schokohase,
Meinst du das man ein Dictionary schon mit JSON Hausmitteln, ala JsonMarshaler, in ein JsonObject serialisieren kann ?
Wäre ja interessant, habe ich noch nicht ausprobiert.

Schokohase 25. Feb 2019 20:07

AW: TDictionary speichern
 
Ja, nee, so nicht ...

Aber die Konvertierung ist relativ simpel:
Delphi-Quellcode:
uses
  System.Generics.Collections,
  System.JSON;

function DictionaryToJsonObject(const ADict: TDictionary<string, string>): TJSONObject;
var
  lPair: TPair<string, string>;
begin
  Result := TJSONObject.Create();
  for lPair in ADict do
  begin
    Result.AddPair(lPair.Key, lPair.Value);
  end;
end;

function JsonToDictionary(const AJson:TJsonObject) : TDictionary<string,string>;
var
  lPair: TJSONPair;
begin
  Result := TDictionary<string,string>.Create();
  for lPair in AJson do
  begin
    Result.Add(lPair.JsonString.Value,lPair.JsonValue.Value);
  end;
end;

Rollo62 26. Feb 2019 06:24

AW: TDictionary speichern
 
Ok, dankesehr für die Klärung.
So in der Art meinte ich das auch, das nenne ich "Array" weil da mehrere Wertepaare hintereinander drin sind.

sko1 26. Feb 2019 10:11

AW: TDictionary speichern
 
Danke Schokohase für das Beispiel, mal sehen ob das hier klappt...

Ciao
Stefan

skoschke 28. Feb 2019 07:29

AW: TDictionary speichern
 
So, nach vielerlei Versuchen, das vernünftig hinzubekommen, bin ich auf die von mir bisher noch nie verwendeten
TBinaryWriter und TBinaryReader gestoßen.

damit war die Umsetzung absolut problemlos:
Schreiben:
Delphi-Quellcode:
    ms.Clear;
    BW := TBinaryWriter.Create(ms, TEncoding.Unicode, false);
    BW.Write(Dict.Count);
    for Pair in Dict do
    begin
      BW.Write(Pair.Key);
      BW.Write(Pair.Value);
    end;
    BW.Free;
Lesen:
Delphi-Quellcode:
    Dict.Clear;
    ms.Position := 0;
    BR := TBinaryReader.Create(ms, TEncoding.Unicode, false);
    anz := BR.ReadInteger;
    for i := 1 to anz do
    begin
      Key := BR.ReadString;
      Value := BR.ReadString;
      Dict.Add(Key, Value);
    end;
    BR.Free;
Damit sind auch die Probleme mit jeglichen Steuer/Sonderzeichen in den Values gelöst, die in der ersten manuellen Variante hätten auftreten können :-)

Ciao
Stefan

Rollo62 28. Feb 2019 08:43

AW: TDictionary speichern
 
Ja die verschollenen Goodies, gut das man die ab und zu mal wieder auskramt.
Das bringt mich auch sofort auf Optimisierungs-Ideen in meinem Code.
Dankesehr fürs Buddeln :thumb:


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