Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi CSV Parser (wieder mal) (https://www.delphipraxis.net/135768-csv-parser-wieder-mal.html)

taveuni 17. Jun 2009 14:32


CSV Parser (wieder mal)
 
Hallo zusammen,

Um es kurz zu machen: Kennt jemand einen CSV Parser (Delphi Klasse) der dies kann:

Beispielzeile (Delimiter=';'):
Dies geht;"Dies muss auch";"Auch dies;ist möglich";
Ausgabe:
-Dies geht
-Dies muss auch (oder "Dies natürlich auch")
-Auch dies;ist möglich (oder "Auch dies;ist möglich")

Die Datei muss ich einlesen und in eine Datenbank speichern.
Die Texte werden aus verschiedenen Systemen automatisiert in eine Excel Datei geschrieben.
Ich erhalte dann jeweils den CSV Export der im Extremfall in einzelnen "Zellen" obige Werte haben kann.
Dann lade ich die Datei in einen Stream und dann in eine TStrings Klasse (LoadFromStream) da ich diese nicht exlusiv öffnen kann.
Bis hier ist alles noch im grünen Bereich. Aber danach..

Gruss Werner

Mithrandir 17. Jun 2009 14:36

Re: CSV Parser (wieder mal)
 
Eventuell der hier.

himitsu 17. Jun 2009 14:43

Re: CSV Parser (wieder mal)
 
Also wenn man sich nur mal estwas aus der System.pas mopst und etwas umbaut, dann dürfte es so auch gehen.

Nun sollte man sich nur noch schnell die Funktionen etwas passender um und fertig :angel2:

Delphi-Quellcode:
function GetParamStr(P: PChar; var Param: string): PChar;
var
  i, Len: Integer;
  Start, S: PChar;
begin
  // U-OK
  while True do
  begin
    while (P[0] <> #0) and (P[0] <> ';') do
      Inc(P);
    if (P[0] = '"') and (P[1] = '"') then Inc(P, 2) else Break;
  end;
  Len := 0;
  Start := P;
  while (P[0] <> #0) and (P[0] <> ';') do
  begin
    if P[0] = '"' then
    begin
      Inc(P);
      while (P[0] <> #0) and (P[0] <> '"') do
      begin
        Inc(Len);
        Inc(P);
      end;
      if P[0] <> #0 then
        Inc(P);
    end
    else
    begin
      Inc(Len);
      Inc(P);
    end;
  end;

  SetLength(Param, Len);

  P := Start;
  S := Pointer(Param);
  i := 0;
  while (P[0] <> #0) and (P[0] <> ';') do
  begin
    if P[0] = '"' then
    begin
      Inc(P);
      while (P[0] <> #0) and (P[0] <> '"') do
      begin
        S[i] := P^;
        Inc(P);
        Inc(i);
      end;
      if P[0] <> #0 then Inc(P);
    end
    else
    begin
      S[i] := P^;
      Inc(P);
      Inc(i);
    end;
  end;

  Result := P;
end;

function ParamCount(const S: String): Integer;
var
  P: PChar;
  S2: string;
begin
  // U-OK
  Result := 0;
  P := PChar(S);
  while True do
  begin
    P := GetParamStr(P, S2);
    if S2 = '' then Break;
    Inc(Result);
  end;
end;

function ParamStr(const S: String; Index: Integer): string;
var
  P: PChar;
begin
    P := PChar(S);
    while True do
    begin
      Dec(Index);
      P := GetParamStr(P, Result);
      if (Index = 0) or (Result = '') then Break;
    end;
  end;
end;
nur die Zeilen muß man dann noch selber einlesen :roll:

taveuni 17. Jun 2009 15:11

Re: CSV Parser (wieder mal)
 
Hallo,

Danke Euch beiden,

Den Link von Daniel G werde ich Morgen anschauen.
Allerdings müsste ich dann ziemlich viel ändern.

Das von himitsu wäre mir symphatischer.
Allerdings muss ich gestehen dass ich da momentan nicht durchsteige :oops:
Wo kann ich da meine Zeile übergeben?

Gruss Werner

himitsu 17. Jun 2009 15:21

Re: CSV Parser (wieder mal)
 
es sollte genauso funktionieren, wie Delphi-Referenz durchsuchenParamStr und Delphi-Referenz durchsuchenParamCount, außer daß man da noch den Zeilen-String mit übergibt.
(das GetParamStr ist nur eine Hilfsfunktion)

Zeile irgendwie aus Datei auslesen
ParamStr(S, 2) ergibt en 3. Wert (Zählung mit 0 beginnend)

PS: in der CodeLib gibt es auch noch Explode, aber ich glaub die Originalversion behandelt kein "

eventuell hilft ja sowas:
Delphi-Quellcode:
Function Explode2(Const S: String): TStringDynArray;
  Var i: Integer;

  Begin
    SetLength(Result, ParamCount(S));
    For i := 0 to High(Result) do
      Result[i] := ParamStr(S, i);
  End;
S = eine Zeile

Der.Kaktus 17. Jun 2009 15:37

Re: CSV Parser (wieder mal)
 
Hallo,
ich nutze seit Delphi4 dieses Tool..mir reicht es und ist einfach.
[c] iss nicht von mir aber Freeware!!!!

Delphi-Quellcode:
unit MyParser;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  TMyParser = class(TComponent)
   private
      FieldSep: char;
      FLine: string;
      NumFields: byte;
      Index, Ct: array[0..255] of integer;
      function Getstr(n: byte): string;
         constructor Create( AParent : TComponent ); override;
    public
      property Sepchar: char read FieldSep write FieldSep;
      property count: byte read NumFields;
      property fields[n: byte]: string read Getstr; default;
      procedure Parse(const Line: string);
    end;

procedure Register;

implementation

constructor TMyParser.Create( AParent : TComponent );
begin
  inherited Create(aParent);
  FieldSep:=' ';
  FLine:='';
  NumFields:= 0;
end;

function TMyParser.Getstr(n: byte): string;
  begin
  result := '';
  if n > NumFields then
    exit;
  if n = 0 then
    result := FLine
  else if n > 0 then
   begin
    dec(n); {0-based arrays!}
    if Index[n] > 0 then
      result := copy(FLine, index[n], ct[n]);
   end;
  end;

procedure TMyParser.Parse(const line: string);
var
 i,p : byte;
 s: string;
 s2 : string;
begin
 Fline := Line;
 s:= line;
 NumFields := 0;
 i := pos(FieldSep, s);
 while i > 0 do
   begin
    s2 := copy (s,1,i -1);
    if NumFields = 0 then
     index[NumFields] := 1
    else
     index[NumFields] := pos(s2,fline);
    ct[NumFields] := length(s2);
    delete(s,1,i);
    i := pos(FieldSep, s);
    inc(NumFields);
   end;
end;




procedure Register;
begin
  RegisterComponents('Parser', [TMyParser]);
end;

end.
Anwendung..auch ganz einfach

Delphi-Quellcode:
  MyParser1.sepchar := ';';
  MyParser1.parse(s);
  for i := 1 to MyParser1.count do ListBox1.items.add(MyParser1.fields[i]);
hoffe, hilft Dir :-D

Blup 18. Jun 2009 07:29

Re: CSV Parser (wieder mal)
 
Alles was dafür notwendig ist, kann bereits TStringlist.
Einfach die Einstellungen richtig setzen und LoadfromFile oder LoadFromStream benutzen.

taveuni 18. Jun 2009 07:59

Re: CSV Parser (wieder mal)
 
Zitat:

Zitat von Blup
Alles was dafür notwendig ist, kann bereits TStringlist.
Einfach die Einstellungen richtig setzen und LoadfromFile oder LoadFromStream benutzen.

Das wage ich zu bezweifeln.
Wie würdest Du denn die Anforderung aus meinem ersten Post mit TStringlist lösen?
Delimiter:=';' und QuotChar:='"'; funktioniert nämlich nicht falls Du dass meinst.
Denn dann Trennt TStringlist bei Leerzeichen wenn keine Quote's vorhanden sind.
Oder hab ich was verpasst?


@Daniel G. : Dein Link funktioniert. Danke.
@Himitsu : Deine Variante natürlich ebenfalls. Danke.
@Kaktus: Deine Variante hab ich nicht ausprobiert aber aus der Distanz scheint der Spezialfall damit nicht abgedeckt zu sein.

Gruss Werner

uligerhardt 18. Jun 2009 08:27

Re: CSV Parser (wieder mal)
 
Zitat:

Zitat von taveuni
Delimiter:=';' und QuotChar:='"'; funktioniert nämlich nicht falls Du dass meinst.
Denn dann Trennt TStringlist bei Leerzeichen wenn keine Quote's vorhanden sind.
Oder hab ich was verpasst?

Vielleicht. :mrgreen: Schau dir mal StrictDelimiter an.

taveuni 18. Jun 2009 09:22

Re: CSV Parser (wieder mal)
 
Stimmt :oops:

Neun Jahre Delphi und keine Kenntnis von StrictDelimiter!
Wieder was gelernt.

Sorry

himitsu 18. Jun 2009 09:30

Re: CSV Parser (wieder mal)
 
Zitat:

StrictDelimiter
das ist (glaub ich) auch "etwas" Neuer?

uligerhardt 18. Jun 2009 09:33

Re: CSV Parser (wieder mal)
 
Zitat:

Zitat von himitsu
Zitat:

StrictDelimiter
das ist (glaub ich) auch "etwas" Neuer?

Jo - http://jedqc.blogspot.com/2005/12/d2...-property.html


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:54 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz