Einzelnen Beitrag anzeigen

Benutzerbild von DGL-luke
DGL-luke

Registriert seit: 1. Apr 2005
Ort: Bad Tölz
4.149 Beiträge
 
Delphi 2006 Professional
 
#7

Re: CSV einlesen und in Stringlist speichern

  Alt 7. Sep 2007, 12:44
Hallo,

habe hier mal ein schnell hingehacktes CSV-To-Stringlist geschrieben. Funktioniert allerdings noch nicht hundertprozentig!

Werde das noch korrigieren, bzw. komplett umschreiben. Hier als komplette Unit:

Delphi-Quellcode:
unit UCSV;

interface

uses Classes;

function CSVToStringList(Text: string; Separator, Escaper, Grouper: Char; UseEscaper, UseGrouper, ResolveEscapings, ResolveGroupings: Boolean): TStrings;

implementation

function GetNextCharPos(Text: string; C: Char; StartPos: Integer): Integer;
var
  i: Integer;
begin
  for i := StartPos to Length(Text) do
    if Text[i] = C then
    begin
      Result := i;
      Break;
    end;
    
end;

function CSVToStringList(Text: string; Separator, Escaper, Grouper: Char; UseEscaper, UseGrouper, ResolveEscapings, ResolveGroupings: Boolean): TStrings;
var
  i: Integer;
  Buffer: string;
  ClosingGrouperPos: Integer;
begin
  Result := TStringList.Create;

  i := 1;
  while i <= Length(Text) do
  begin
    if (Text[i] = Separator) or ((i = Length(Text)) and (Buffer <> '')) then
    begin
      Result.Add(Buffer);
      Buffer := '';
      Inc(i)
    end
    else if (Text[i] = Escaper) and (UseEscaper) then
      if ResolveEscapings then
      begin
        Buffer := Buffer + Text[i+1];
        Inc(i,2);
      end
      else
      begin
        Buffer := Buffer + Text[i+1] + Text[i+2];
        Inc(i,2);
      end
    else if (Text[i] = Grouper) and (UseGrouper) then
    begin
      repeat
        ClosingGrouperPos := GetNextCharPos(Text,Grouper,i+1);
      until (Text[ClosingGrouperPos-1] <> Escaper) or (not UseEscaper);

      if ResolveGroupings then
        Buffer := Copy(Text,i+1,ClosingGrouperPos-1)
      else
        Buffer := Copy(Text,i,ClosingGrouperPos);
      i := ClosingGrouperPos + 1; //we will hit the separator in next iteration and flush the buffer.
    end
    else
    begin
      Buffer := Buffer + Text[i];
      Inc(i);
    end;
  end;
end;

end.
Benutzung:

In Text muss der komplette CSV-String übergeben werden.
In Separator der Char, der die einzelnen Datensätze trennt, also typischerweise ';'.
In Escaper ein Escapechar, der dafür sorgt, dass der ihm folgende Char keinesfalls als Steuerzeichen erkannt wird, also z.B. '\'.
Beispiel:
Code:
*;abc\;def\\;*
Wird als folgender Datensatz erkannt:
Code:
abc;def\
(Doppelte Angabe des Escapechars führt zur Erkennung eines einfachen Vorkommens des Escapechars als Literal!)
In Grouper ein Char, der einen Datensatz begrenzt, damit z.B. der Separator darin vorkommen kann:
Code:
*;"abc;def";*
wird zu
Code:
abc;def
UseEscaper und UseGrouper werden benutzt, um festzulegen, ob der übergebene Escaper/Grouper interpretiert werden.
Wenn z.B. Escaper='\', aber UserEscaper auf false steht, wird folgendes:
Code:
*;abc\def;'*
zu
Code:
abc\def
Auch der Grouper wird dann als ganz normales Literal in den erkannten Datensatz übernommen.

Wenn ResolveEscapings bzw. ResolveGroupings auf true ist, werden Escaper und Grouper aus dem erkannten Datensatz entfernt.
Das obige Beispiel für Escaper nimmt an, dass ResolveEscapings auf true steht; ansonsten würde das Ergebnis so aussehen:
Code:
abc\;def\\
Das escapete Semikolon wird also erkannt und nicht als Separator behandelt, der Escaper davor wird aber stehengelassen.
Lukas Erlacher
Suche Grafiktablett. Spenden/Gebrauchtangebote willkommen.
Gotteskrieger gesucht!
For it is the chief characteristic of the religion of science that it works. - Isaac Asimov, Foundation I, Buch 1
  Mit Zitat antworten Zitat