Thema: Delphi TClientDataSet füllen

Einzelnen Beitrag anzeigen

jbg

Registriert seit: 12. Jun 2002
3.483 Beiträge
 
Delphi 10.1 Berlin Professional
 
#3

AW: TClientDataSet füllen

  Alt 10. Mai 2024, 20:56
Deine WideString-Spalten haben eine maximale Länge von 0. Da passt nicht viel rein.

Zitat:
CSVDataSet.FieldDefs.Add(FieldNames.Strings[i],ftWideString, ----> 0 <---- ,False);
Zudem wird für das ClientDataSet ein "ChangeLog" geschrieben, welches Speicher beansprucht und dazu dient, einen "Rollback" durchzuführen. Wenn du das nicht brauchst, wovon ich ausgehe, dann kannst du das deaktivieren, bevor du die Daten in das CDS reinkoppst.

Delphi-Quellcode:
CSVDataSet.CreateDataSet;
CSVDataSet.Active:=True;
CSVDataSet.LogChanges := False; // Kein ChangeLog führen

Da du als Ergebnis eine CSV Datei haben möchtest, ist ein ClientDataSet in meinen Augen ungeeignet, da es immens Speicher frisst und zudem auch noch langsam ist. Vor allem musst du beim CDS wissen, wie viele Zeichen maximal in ein Feld kommen, denn ein Verbreitern von Spalten ist nicht möglich. Und wenn du die Spaltenbreite zu hoch einstellst, verbrennst du Arbeitsspeicher, denn auch ein String mit nur einem Zeichen braucht im CDS den Speicher für die maximale Zeichenanzahl der Spalte.

Eine andere Lösung wäre sich eine Klasse (TMyCSVRow) zu schreiben, die alle Zielfelder enthält. Dann die erste CSV-Datei einlesen und während dessen für jede Zeile ein Objekt erzeugen und dieses in ein Dictionary<T, TMyCSVRow> packen. Danach die zweite CSV-Datei einlesen und im Dictionary das Objekt zur ID suchen (Fehlerfall, ID ist nicht vorhanden beachten) und die weiteren Objektfelder befüllen. Wenn alle CSV-Dateien so eingelesen wurden, kannst du über die Dictinary-Values drüber iterieren (for-in) und die CSV-Datei schreiben. Und wenn die Reihenfolge der Zeilen der Ziel-CSV-Datei wichtig ist (TDictionary wirft sie durcheinandern), könne man die Objekte zusätzlich in eine TList<TMyCSVRow> packen und beim Schreiben der Ziel-CSV-Datei diese durchlaufen anstatt des Dictionary. Die Freigabe der Objekte im TDictionary oder TList darf natürlich nicht vergessen werden.
Dieses Vorgehen verbraucht um einiges weniger Speicher und ist um ein vielfaches schneller.

Obiges könnte man auch Quick&Dirty mit einer TStringList als "Klasse" bauen und die Reihenfolge der Strings in der StringList gibt die Ziel-Spalte an. Somit hätte man ein TDictionary<T, TStringList>.
  Mit Zitat antworten Zitat