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:
Wird als folgender Datensatz erkannt:
(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:
wird zu
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:
zu
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:
Das escapete Semikolon wird also erkannt und nicht als Separator behandelt, der Escaper davor wird aber stehengelassen.