Entwickler-Ecke

Dateizugriff - csv-Datei einlesen


Hänsel - So 10.11.19 13:23
Titel: csv-Datei einlesen
Hallo,

ich möchte verschiedene .csv-Dateien in eine Datenbank(MSQL)einlesen. Das Problem liegt darin, die einzelnen Datensätze innerhalb einer csv-Datei sind unterschiedlich lang. Ich würde bei jeder einzelnen Zeile die Satzlänge (wieviel Felder hat diese Zeile)abfragen.

Meine Frage: wie kann man diese bei einer csv-Datei realisieren.


Danke im Voraus
Hänsel


jaenicke - So 10.11.19 14:02

Falls du eine aktuelle Enterprise / Architect Edition von Delphi benutzt, kannst du zum Zugriff einfach die Enterprise Connectors verwenden, die sind da seit kurzem dabei, auch für den Zugriff auf .csv Dateien. Dann bekommst du daraus einfach ein Dataset:
https://www.embarcadero.com/de/products/enterprise-connectors
Die Daten könntest du dann direkt mit Local-SQL aus dem CSV-Dataset in das Zieldataset schieben.

Ansonsten kannst du die Datei zeilenweise durchgehen und die einzelnen Felder manuell auslesen. Wenn dort keine Semikola außer den Trennzeichen enthalten sind, geht das einfach mit einer TStringList und Delimiter/DelimitedText, mit ExtractStrings aus System.Classes [http://docwiki.embarcadero.com/Libraries/Rio/en/System.Classes.ExtractStrings] oder mit SplitString aus System.StrUtils [http://docwiki.embarcadero.com/Libraries/Rio/en/System.StrUtils.SplitString] oder mit dem Stringhelper 'DeinStringWert'.Split() seit XE3 [http://docwiki.embarcadero.com/Libraries/Rio/en/System.SysUtils.TStringHelper.Split].

Der Stringhelper kann auch mit Anführungszeichen usw. umgehen und ist daher ab XE3 die beste Option.

Und dann gibt es natürlich noch diverse CSV-Zugriffsbibliotheken, die du nehmen könntest.


Hänsel - So 10.11.19 16:55

Danke für die Hinweise.
Ich werde alles Zeile für Zeile abfragen müssen. Da diese unterschiedlich lang sind, hätte da jemand für mich einen Ansatz dafür? Die Felder sind mit einem Semikolon getrennt.In der ersten Zeile stehen die Feldnamen (alles o.k.)Mir geht es um die Abfrage am Zeilenende.


Danke im Voraus

Hänsel


Narses - So 10.11.19 19:18

Moin!

Lies die Datei in eine TStringList ein, dann hast du die Zeilen getrennt. Jetzt nimmst du jede Zeile (=ein Element aus der TStringList) und zählst die Anzahl der Semikola darin -> +1 = Anzahl der Datenfelder. :nixweiss:
Ehrlich gesagt, was soll das für eine komische Datei sein, wenn in der ersten Zeile die Spaltenbeschriftungen stehen, dann machen unterschliedlich lange Datensätze danach irgendwie keinen Sinn... ? :gruebel:

cu
Narses


Sinspin - So 10.11.19 23:52

Hallo, wie meinst du das mit unterschiedlich lang? Die Zeilen haben eine unterschiedliche Anzahl von Feldern? Oder die Zeilenlängen sind einfach unterschiedlich?
Das CSV Format definiert ein einheitliches Vorgehen beim kodieren von Text in dem Leerzeichen oder Trenner enthalten sind wobei mit dem trenner einzelenen Felder unterschieden werden.
Du brauchst zum einlesen einer solchen Datei zwei Stringlisten. Die erste, ich nenne sie mal SL, lädt die komplette Datei via LoadFromFile.
Die zweite Stringliste, hier mal mit Line bezeichnet, wird erst configuriert, so dass der Feldtrenner in CommaText eingetragen ist. Normalerweise braucht man das nicht ändern wenn man CSV einliest.
über n = 0..SL.Count-1
Line.CommaText := SL.Strings[n]
über x = 0.. Line.Count-1
Line.Strings[x] liefert die Feldnamen oder Feldinhalte falls die erste Zeile keine Namen enthält.


jaenicke - Mo 11.11.19 07:14

user profile iconHänsel hat folgendes geschrieben Zum zitierten Posting springen:
Ich werde alles Zeile für Zeile abfragen müssen. Da diese unterschiedlich lang sind, hätte da jemand für mich einen Ansatz dafür?
Zeig doch einfach mal wie weit du kommst. Dann können wir sicher auch besser helfen. Denn einige Möglichkeiten hatte ich ja verlinkt und user profile iconNarses und user profile iconSinspin haben ja jetzt auch noch Hinweise gegeben.

Im Moment ist mir nicht klar womit du eigentlich Probleme hast. Das Splitten pro Zeile scheint ja zu klappen, wenn ich das richtig interpretiert habe:
user profile iconHänsel hat folgendes geschrieben Zum zitierten Posting springen:
In der ersten Zeile stehen die Feldnamen (alles o.k.)

Die
user profile iconHänsel hat folgendes geschrieben Zum zitierten Posting springen:
Abfrage am Zeilenende
hängt davon ab was du dann mit den Daten machen möchtest. Denn erst einmal kannst du mit einer Schleife ja alle Elemente durchgehen, egal wie viele es in einer Zeile sind. Die Schleifenenden hat user profile iconSinspin ja mittlerweile auch genannt.


doublecross - Mo 11.11.19 10:19

Hi,
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Ehrlich gesagt, was soll das für eine komische Datei sein, wenn in der ersten Zeile die Spaltenbeschriftungen stehen, dann machen unterschiedlich lange Datensätze danach irgendwie keinen Sinn... ? :gruebel:

da sind mir in meiner Karriere schon etliche CSV "ähnlice" Dateien untergekommen in den es solche Situationen gab.

Beliebt sind so Dinge wie: Das erste Feld der Zeile bestimmt welche Felder wirklich gefüllt werden
oder: Wenn eine Leerzeile auftaucht ist die Zeile danach ein neuer "Tabellenanfang", sie enthält also die Feldnamen der nächsten Datenstruktur.

Da gibt es die "interessantesten" Konstrukte. in freier Wildbahn.

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Lies die Datei in eine TStringList ein, dann hast du die Zeilen getrennt. Jetzt nimmst du jede Zeile (=ein Element aus der TStringList) und zählst die Anzahl der Semikola darin -> +1 = Anzahl der Datenfelder.


In dem Fall muss man aber aufpassen, wenn es gequotete Texte gibt, dann muss man die Semikola welche in quotes stehen wieder gesondert behandeln und gegebenenfalls die Quote Symbole entfernen. Alles kein Hexenwerk, man sollte sich der Sonderfälle aber bewusst sein, ehe man loslegt.

doublecross


Hänsel - Mo 11.11.19 11:57

Hallo ,

anbei habe ich mal einen Ausschnitt aus einer csv-Datei beigelegt.

Quelltext
1:
2:
3:
4:
5:
6:
Zeile 2  RAW4DATE  01-01-0001  //Zeile 2/3/4 enden hier    
Zeile 3  RAW4DATE  01-01-0001    
Zeile 4  RAW4DATE  01-01-0001    
Zeile 5   27  Einheiten  (H.C.A.)   15.01.2018  52          Zeile 5/6/7 enden hier
Zeile 6   60  Einheiten  (H.C.A.)   15.01.2018  110
Zeile 7   0,007  m³ Volumen   31.05.2018  0,006

Weiter Zeilen können aber auch noch andere Satzlängen haben.

Gibt es nicht die Möglichkeit vor Beginn z.B. der Zeile 2 die Anzahl der Felder zu Zählen. Wenn ja wie?
Noch soviel dazu, von hieraus (csv) werden die Daten in eine SQL Tabelle geschrieben. Die Fehlermeldung erscheint dann, wenn ich z.B. bei Zeile 2 am Satzende bin und weiter das nächste Feld (was es ja nicht gibt) abfrage.

MFG
Hänsel

Moderiert von user profile iconTh69: Code-Tags hinzugefügt


doublecross - Di 12.11.19 10:00

Hi,

user profile iconHänsel hat folgendes geschrieben Zum zitierten Posting springen:
anbei habe ich mal einen Ausschnitt aus einer csv-Datei beigelegt.


was ist denn da als Trennzeichen Verwendet? Ein Tab? Oder haben die Felder eine Feste Bereite? Woher weißt du, wie du den Wert aus Spalte X zu interpretieren kannst?


Hänsel - Di 12.11.19 22:35

Hi
Danke für alle Hinweise.
Meine Frage ist indessen beantwortet.

Nochmals Danke


Sinspin - So 17.11.19 22:34

Hallo, wäre schön zu wissen wo und wie deine Frage beantwortet wurde, so dass wir alle was davon haben.

Danke auch.