Autor Beitrag
GuaAck
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 378
Erhaltene Danke: 32

Windows 8.1
Delphi 10.4 Comm. Edition
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 82



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1335
Erhaltene Danke: 118

Win 10
RIO, CE, Lazarus
BeitragVerfasst: Mi 24.07.13 06:46 
user profile iconOldGrumpy hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 24.07.13 10:20 
Nebenbei, in XE4 ginge das auch so:
ausblenden 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([';']);
    // CurrentLineValues[0]...
  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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
EE-Maler
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)
BeitragVerfasst: Mi 24.07.13 10:37 
user profile iconSinspin hat folgendes geschrieben Zum zitierten Posting springen:
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:

ausblenden 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 94
Erhaltene Danke: 11

Win 7, DOS5
Delphi 2007 Architect, BP7/TP5, LISP, PS
BeitragVerfasst: Mi 24.07.13 11:57 
user profile iconSinspin hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
EE-Maler
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)
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 94
Erhaltene Danke: 11

Win 7, DOS5
Delphi 2007 Architect, BP7/TP5, LISP, PS
BeitragVerfasst: Mi 24.07.13 18:21 
.. danke. Ähnlich wie bei SQL mit den doppelten Tüddelchen innerhalb eines mit Tüddelchen umgrenzten Stringalterals.