Entwickler-Ecke

Dateizugriff - csv-Datei einlesen


Hänsel - So 23.02.20 10:35
Titel: csv-Datei einlesen
Kann hier jemand weiterhelfen?

das Einlesen der csv-Datei funktioniert eigentlich ganz ordentlich aber die letzte Zeile wird grundsätzlich nicht mit Eingelesen. Was habe ich da vergessen bzw. falsch gemacht.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
procedure TForm_M_Satz_Einlesung.Import1FromCSVfile(sFile: string);
var
   ON,su,aus,be: string;
   tb,zah: Integer;

   tfDatei: TextFile;
   sZInhalt,D,ob : string;
   slWerte: TStringList;
   iZeile,zähler: Integer;
begin
   Try
     Try
       AssignFile(tfDatei, sFile);
       Reset(tfDatei);
       iZeile:= -1;
       while not EoF(tfDatei) do
        begin
         slWerte := TStringList.Create;
         slWerte.StrictDelimiter:=true;
         slWerte.Delimiter := #9;
         slWerte.DelimitedText := sZInhalt;
         Readln(tfDatei,sZInhalt);
         Inc(iZeile); // erste Zeile ist der Kopf
         if iZeile > 0 then // alles größer als Zeile eins sind Daten
           begin
           DataModule1.ADOQuery_M_Satz.Open;
           DataModule1.ADOQuery_M_Satz.Append;
           DataModule1.ADOQuery_M_Satz.Edit;
           DataModule1.ADOQuery_M_Satz['Zeile']:=slWerte.Strings[0];
           end;
           DataModule1.ADOQuery_M_Satz.Edit;
           DataModule1.ADOQuery_M_Satz.Post;
       end;
     Finally
     End;
   Finally

   End;
End;


Danke im Voraus
Hänsel

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


Sinspin - So 23.02.20 13:31

Hallo. Verwende doch einfach zwei Stringlisten. Eine für die Datei, die dann die Zeilen enthält, so ist jede Zeile ein Record.
Und eine zweite die dann eine Zeile nach der anderen erhält um jeweils das CSV aufzudröseln, wie Du es ja schon machst.
Dann sind auch alle Probleme weg die sich sonst bei MBCS (Multi Byte Char Sets) ergeben würden.


ub60 - So 23.02.20 13:33

Kann es sein, dass in der letzten Zeile der CSV-Datei ein LineFeed bzw. CR fehlt?
Dann würde readln die letzte Zeile nicht mit einlesen.

Vorschlag 2: Verwende zum Einlesen auch eine StringListe. (Edit: Sispin war schneller :) )

ub60


Hänsel - So 23.02.20 15:41

Hallo
Danke für die Hinweise.
Ich habe mit Stringlisten noch nichts gemacht. Könnte ich eventuell ein Beispiel für mein Problem von Euch bekommen? Wäre super.


Hänsel


Gausi - So 23.02.20 16:13

Das sollte in etwa so gehen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
  StringListDatei := TStringList.Create;
  try
    StringListDatei.LoadfromFile(sFile);
    for i := 0 to StringListDatei.Count - 1 do
    begin
       // im Wesentlichen  der Code aus der While-Schleife.
       // eine Zeile bekommst du hier mit StringListDatei[i]
    end
  finally
    StringListDatei.Free;
  end;


Wenn die Dateien sehr groß sind (so ab ein paarhundert MB), bekommst du hier allerdings ggf. ein Speicherproblem.


Hänsel - So 23.02.20 16:47

Hallo,
Danke für den Hinweis.
Hänsel


icho2099 - Mo 24.02.20 08:43

Du erzeugst in der while Schleife bei jedem Durchlauf eine neue Stringlist, und du weist dieser dann die Zeile zu, die du im vorherigen Durchlauf gelesen hast. Der letzte Durchlauf liefert dir keinen Input in die Stringlist.
Natürlich sollte die Stringlist vor der Schleife erstellt und in der Schleife gefüllt und wieder geleert werden. Und nach der Schleife das Aufräumen nicht vergessen.

Moderiert von user profile iconTh69: Beitragsformatierung überarbeitet.


hRb - Sa 14.03.20 15:10

Hallo Hänsel,
ich arbeite relativ viel mit csv-Dateien. Da gibt es noch deutlich mehr Fallstricke die zu beachten sind und meine selbstgestrickte Einleseroutine ist recht umfangreich. Beispiele:
1. csv-dateien haben nicht selten innerhalb eines Teiltextes noch Zeilenumbruch-Steuerzeichen, also #0D, #0A. Dann wird der Text oft in Doppel-Hochkomma "....." gesetzt. Die normale readln-Funktion erkennt dies nicht, d.h. Du bekommst ungewollt eine neue Zeile und die Tabellen-Struktur wird falsch.
2. Bei csv sind mehrere Trennzeichen erlaubt , z.B Tab ; | etc.. Auch dies muss vorab eingestellt oder autom. erkannt werden (Strukturanalyse).
Wenn Du also ganz allgemein csv-Dateien selbst einlesen möchtest, musst Du Dich intensiv mit den Regeln des csv-Formats beschäftigen. Überlege mit Excel zu öffnen und von dort Daten übernehmen.
3. Aber auch wenn Du dies tust kanns Probleme geben. Ich arbeite z.B. häufig mit einer csv-Exportdatei einer kirchlichen Datenbank. Wird dort unter der Spalte "Kirchenbuch/Seite" z.B. der Text 2/7 eingetragen, was bedeuten soll KirchenbuchNr 2, Seite 7, so interpretiert Excel dies als Datum 02.07.2020 (aktuellesJahr).
Es gibt also genug Fehlermöglichkeiten.
hRb


hRb - Mi 18.03.20 21:54

Hallo Hänsel,
noch ein Nachtrag.
Du hast vor 7 Monaten schon einmal eine Frage zum Einlesen von csv-Dateien gestellt. Du schreibst dort, nachdem Du eine Reihe von Hinweisen bekommen hast, dass die Frage gelöst sei. Danach wird nachgefragt wie denn die Lösung war.
1. Die Frage ist nach wir vor im Forum als "Offen" , also ungelöst markiert. VERGESSEN?
2. Du hast, obwohl man Dir Hilfetipps gegeben hat, nicht mehr geantwortet wie die Lösung war.
Nun stellst Du unter gleichem Stichwort die nächste Frage. Ich finde, wer Fragen stellt, sollte den Dialog auch zu Ende bringen, damit andere auch etwas davon haben. Wäre doch bei so viel ehrenamtlichen Einsatz eigentlich fair.
Gruß hRb