Einzelnen Beitrag anzeigen

Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.837 Beiträge
 
Delphi 10 Seattle Enterprise
 
#36

AW: csv Datei Import ClassHelper für TClientDataSet

  Alt 17. Mai 2019, 17:03
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.
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)

Geändert von MaBuSE (17. Mai 2019 um 17:34 Uhr)
  Mit Zitat antworten Zitat