Autor |
Beitrag |
GuaAck
      
Beiträge: 378
Erhaltene Danke: 32
Windows 8.1
Delphi 10.4 Comm. Edition
|
Verfasst: Di 23.07.13 22:52
Hallo,
ich möchte eine CSV-Datei auswerten, also eine Textdatei mit Zeilen der Art:
Wert1;Wert2;Wert3;
Ich kenne den Typ von Wert1, Wert2 und Wert 3.
Ich habe mal eine sehr schöne Funktion in Delphi dafür genutzt, leider habe ich die aber in der Hilfe und meinen Projekten nicht mehr finden können. Es ging im Prinzip so:
Trennzeichen_festlegen (';');
Lese(Wert1); {Liest bis ';' und setzt dann den Lesezeiger auf die Position nach dem nächsten ';'}
Lese(Wert2);
Lese(Wert3);
Vielleicht war es eine Funktion in der Stringverarbeitung, vielleicht auch im Bereich TStream, da habe ich aber nichts finden können.
Kennt jemand so eine Funktion?
(Klar, als Notlösung scanne ich den String einer Zeile selbst, zerlege ihn in seine Einzelteile und wandele z. B. mit strtoint, strtofloat usw. um. Ist aber umständlicher.)
Gruß GuaAck
|
|
OldGrumpy
      
Beiträge: 82
|
Verfasst: Mi 24.07.13 00:14
Wenn es nicht allzu viele Daten sind und die Geschwindigkeit nicht zu kritisch ist, kann man TStringList dafür missbrauchen, zum Beispiel so:
- Zwei TStringList instantiieren.
- Ab (IIRC) D2005 unbedingt StrictDelimiter:=True setzen (war früher Default, ab der Version ist es umgekehrt), Delimiter auf Semikolon setzen.
- In die erste die CSV-Datei laden (LoadFromFile)
- In einer Schleife jeweils eines der Items der ersten TStringList als DelimitedText der zweiten StringList setzen. Und schon ist die CSV-Zeile getrennt.
Stößt allerdings an seine Grenzen, wenn das Trennzeichen auch innerhalb der Felder vorkommt - die Tauglichkeit hängt also von den Daten ab. Ein fertiges Äquivalent zu explode() aus PHP beispielsweise habe ich aber auch schon mehrfach rumgehen sehen.
|
|
Sinspin
      
Beiträge: 1335
Erhaltene Danke: 118
Win 10
RIO, CE, Lazarus
|
Verfasst: Mi 24.07.13 06:46
OldGrumpy hat folgendes geschrieben : | Stößt allerdings an seine Grenzen, wenn das Trennzeichen auch innerhalb der Felder vorkommt - die Tauglichkeit hängt also von den Daten ab. Ein fertiges Äquivalent zu explode() aus PHP beispielsweise habe ich aber auch schon mehrfach rumgehen sehen. |
CSV ist ein Standard für Tabellen im Textformat und kann damit umgehen das die Trennzeichen in den Strings enthalten sein können. Mit zwei TStringList ist eine CSV Datei recht komfortabel zu lesen. TStringList verarbeitet auch großen Dateien erstaunlich schnell.
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 24.07.13 10:20
Nebenbei, in XE4 ginge das auch so: Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| uses System.SysUtils, System.IOUtils;
var CurrentLine: string; CurrentLineValues: TArray<string>; begin for CurrentLine in TFile.ReadAllLines('blubb.csv') do begin CurrentLineValues := CurrentLine.Split([';']); end; | Aber ich vermute mal anhand deiner Profilangabe, dass du das nicht nutzen kannst.
Für echte CSV-Dateien ist ein entsprechender Reader aber sinnvoller.
|
|
Xion
      

Beiträge: 1952
Erhaltene Danke: 128
Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
|
Verfasst: Mi 24.07.13 10:37
Sinspin hat folgendes geschrieben : | CSV ist ein Standard für Tabellen im Textformat und kann damit umgehen das die Trennzeichen in den Strings enthalten sein können. |
CSV kann das, aber der vorgeschlagene Algorithmus eben nicht. Zum Beispiel:
Quelltext 1:
| 1,"""Siehe da"", sagte er",14 |
Dann kommt man nicht mehr weit, wenn man nur bis zum nächsten Komma kopiert
Es hängt natürlich ganz davon ab, woher diese CSV kommt, ob sowas überhaupt vorkommt. Sind alle Spalten z.B. Integer, dann sollte es keine Probleme damit geben. Da die Zeilen aber gegen jeden Standard durch ";" getrennt werden, vermute ich, dass da eine Excel-Tabelle dahinter steckt.
Man bräuchte wohl so eine Art Zustandsmaschine. Lese bis zum nächsten Trennzeichen oder ". Wenn " gelesen und es folgt noch eins, dann wird es durch ein " ersetzt. Sonst beginnt hier ein String und endet erst beim nächsten einfachen ", Trennzeichen dazwischen sind also zu ingorieren. Immer wenn man dann ein Trennzeichen gefunden hat, schneidet man das Stück ab und gibt es zurück.
Wenn man Typen kennt, kann man die gleich prüfen und eine vernünftige Fehlerbehandlung durchführen.
Wenn man auf das alles verzichtet, dann sieht die einfachste Variante wohl in etwa so aus:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| var csv: TextFile; S: String; AssignFile(csv,path+'my.csv'); Reset(csv); while not EoF(csv) do begin ReadLn(csv,S); S:=S+';'; while Pos(';',S)>0 do begin Spalte := Copy(S,1,Pos(';',S)-1); S := Copy(S,Pos(';',S)+1,MaxInt); end; end; CloseFile(csv); |
_________________ a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 24.07.13 10:49
Noch einfacher ist aber gleich einen fertigen Reader zu benutzen wie diesen hier...
www.delphipraxis.net...von-csv-dateien.html
Für diesen Beitrag haben gedankt: GuaAck
|
|
MeierZwoo
      
Beiträge: 94
Erhaltene Danke: 11
Win 7, DOS5
Delphi 2007 Architect, BP7/TP5, LISP, PS
|
Verfasst: Mi 24.07.13 11:57
Sinspin hat folgendes geschrieben : | CSV ist ein Standard für Tabellen im Textformat und kann damit umgehen das die Trennzeichen in den Strings enthalten sein können. |
Wie unterscheidet dann wer (?) Trennzeichen und Trennzeichen innerhalb eines Strings?
mfg
|
|
Xion
      

Beiträge: 1952
Erhaltene Danke: 128
Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
|
Verfasst: Mi 24.07.13 13:22
Texte werden üblicherweise mit " umgeben. Bsp:
1,"Apfel",15
Steht jetzt ein Trennzeichen im String ist das kein Problem, denn es ist eindeutig, dass dieses zum String gehört:
1,"Apfel,Birne",15
Einziges Problem dabei ist, wenn ebenfalls ein " im String vorkommt, weshalb diese immer escaped werden (bei csv doppelt notiert)
Statt
1,"51° 14′ 4,2"",15
heißt es also:
1,"51° 14′ 4,2""",15
Der Parser kennt das Prinzip und weiß zum einen, dass "" nichts mit der Begrenzung des Strings zu tun hat, und dass er "" danach wieder durch " ersetzen muss.
Das ist eigentlich so üblich, wobei es scheinbar kein genormtes CSV-Format gibt. An die Anführungszeichen halten sich wohl noch die meisten, das Trennzeichen selbst ist meist verschieden. Comma Seperated Values gibt also auch mit Strichpunkt oder Leerzeichen getrennt. Und dann gibt es natürlich sehr viele Codes, die das mit den Anführungszeichen nicht richtig berücksichtigen, sowohl beim Import als auch beim Export 
_________________ a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)
|
|
MeierZwoo
      
Beiträge: 94
Erhaltene Danke: 11
Win 7, DOS5
Delphi 2007 Architect, BP7/TP5, LISP, PS
|
Verfasst: Mi 24.07.13 18:21
.. danke. Ähnlich wie bei SQL mit den doppelten Tüddelchen innerhalb eines mit Tüddelchen umgrenzten Stringalterals.
|
|
|