Hi Folks,
hier eine Implemtierung für LF in Quoted-Fields:
...
Über Feedback würde ich mich freuen.
HTH somebody
Hallo,
ich glaube Deine Lösung würde fehlschlagen, wenn in der 1. Zeile schon ein CRLF in einem Feld enthalten ist.
Wenn ich das beim Lesen richtig verstanden habe entfernst Du einfach die CRLF
myString := myString + slFile[myPos];
. Sie sind dann auch beim Speichern nicht mehr enthalten.
Ich würde noch einen anderen Ansatz vorstellen.
Man könnte die CRLF in den Quoted Fields auch per Regular Expression identifizieren und dann durch ein String ersetzen. Beim Zuweisen der Felder würde man das dann wieder rückgängig machen. Damit sind die CRLF auch in den Datenbank Feldern enthalten.
Damit würde das Beispiel eines ClassHelpers und der einfachen Konvertierung von
CSV Dateien via TStringList um ein Beispiel zur Verwendung von System.RegularExpressions und die Verwendung eines Records zum "Erzeugen einer Methode" erweitert
Ich hab mal schnell so was zum Maskieren der CRLF geschrieben. In diesem Beispiel wird das " verwendet. Das kann man natürlich auch noch variabel gestalten.
Der String
'"[^"]*\n[^"]*"'
müsste dann entsprechende angepasst werden.
Bei Param
const QuoteChar: Char = '"'
wäre das dann so was wie
QuoteChar+'[^'+QuoteChar+']*\n[^'+QuoteChar+']*'+QuoteChar
oder
Format('%s[^%0:s]*\n[^%0:s]*%0:s', [QuoteChar])
.
Anmerkung zu RegEx. Der verwendete Ausdruck
'"[^"]*\n[^"]*"'
wurde von mir verwendet, da
'".*\n.*"'
nicht funktioniert, da das * greedy ist. (Siehe
https://www.regular-expressions.info/repeat.html )
Anmerkung zum Replace: Ich habe das an das Beispiel aus der Dokumentation angelehnt (Siehe
http://docwiki.embarcadero.com/CodeE...place_(Delphi) )
Mit MaskCRLF werden alle CRLF in "" durch ^P ersetzt.
Mit UnMaskCRLF wird das wieder zu CRLF.
In
LoadFromFile müssten nur 2 Zeilen ergänzt werden.
SaveToFile müsste natürlich auch entsprechend geändert werden.
Delphi-Quellcode:
...
uses Unit2;
// Die Unit einbinden.
...
// TClientDataset füllen
DisableControls;
slFile.Text := MaskCRLF(slFile.Text);
// <----- Diese Zeile ist neu ;)
for i := 0
to slFile.Count - 1
do
begin
slRow.DelimitedText := slFile[i];
Append;
for j := 0
to slRow.Count - 1
do
begin
// Fields[j].AsString := slRow[j];
Fields[j].AsString := DeMaskCRLF(slRow[j]);
// <----- Diese Zeile wurde geändert ;)
end;
Post;
end;
EnableControls;
...
Hier ist die verwendete Unit2.pas:
(Ich hab sie noch nicht gespeichert, deshalb hab ich mir auch noch keinen Gedanken über den
Unit-Namen gemacht
Delphi-Quellcode:
unit Unit2;
interface
function MaskCRLF(
const Source:
string; Mask:
string = '
^P'):
string;
function DeMaskCRLF(
const Source:
string; Mask:
string = '
^P'):
string;
implementation
uses
System.SysUtils, System.RegularExpressions;
type
TmyReplaceRec =
record
Mask:
string;
function MyReplace(
const Match: TMatch):
string;
end;
function TmyReplaceRec.MyReplace(
const Match: TMatch):
string;
begin
Result := System.SysUtils.StringReplace(Match.Value, #13#10, Mask, [rfReplaceAll]);
end;
function MaskCRLF(
const Source:
string; Mask:
string):
string;
var mr: TmyReplaceRec;
begin
mr.Mask := Mask;
Result := TRegEx.Replace(Source, '
"[^"]*\n[^"]*"', mr.MyReplace, [roSingleLine]);
end;
function DeMaskCRLF(
const Source:
string; Mask:
string):
string;
begin
Result := System.SysUtils.StringReplace(Source, Mask, #13#10, [rfReplaceAll]);
end;
end.