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>.