Autor Beitrag
Hänsel
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 144



BeitragVerfasst: Sa 08.05.21 14:01 
Hallo, habe folgendes Problem:
meine bisherige Einlesung einer csv-Datei ging soweit i.o. Diese sah wie folgt aus:
ausblenden Quelltext
1:
2:
SND_NR;EFE;84112595;29h;HCA;Response,Uplink,TPL=S,M-Bus;126;00h;5;19.03.2021 09:04 invalid 0 summer time
0;1289;31.12.20;842;31.12.19;213;91;77;72;55;48;86;30;0;1;1;0;0;0;0;1;0;0;0;0;1;8;58;54;46;73;97;147;57;53;0;00.00.2000 00:00 invalid 0 summer time 0;

«File completely written» ohne die letzte Zeile.

Jetzt hat der Lieferant der csv-Datei am Ende dies hinzugefügt: «File completely written»
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
while not EoF(tfDatei) do
begin
  slWerte := TStringList.Create;
  Readln(tfDatei,sZInhalt);
  slWerte.StrictDelimiter := true;
  slWerte.DelimitedText := sZInhalt;
  slWerte.Delimiter :=';';
  slWerte.DelimitedText:=sZInhalt;
  slWerte.QuoteChar := '"';
  slWerte.DelimitedText:=sZInhalt;
  Inc(iZeile); // erste Zeile ist der Kopf
               
  //  Einlesung aller Daten

end;
CloseFile(tfDatei);

Durch die letzte Zeile bekomme ich immer wieder eine Fehlermeldung, da die Einlesung erst mit der letzten Zeile endet.
Was habe ich hier falsch gemacht? Bzw. was habe ich bei der Vorbereitung zur Einlesung vergessen?

War kann hier helfen?
Danke im Voraus
Hänsel

Moderiert von user profile iconTh69: Code-Tags hinzugefügt
Moderiert von user profile iconTh69: Delphi-Tags hinzugefügt
Moderiert von user profile iconTh69: Titel geändert (war "Einlesung einer csv-Datei").
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 08.05.21 14:33 
Welche Fehlermeldung kommt denn und an welcher Stelle? In dem geposteten Teil des Quelltext sehe ich auf Anhieb nichts Verdächtiges.

Warum weist du eigentlich DelimitedText mehrfach zu? Das ist doch unnötig und langsam.

Prüfst du denn die Daten bevor du sie verarbeitest? Oder gehst du vielleicht einfach davon aus, dass eine bestimmte Anzahl von Spalten vorhanden ist?
Hänsel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 144



BeitragVerfasst: So 09.05.21 08:06 
Hallo,
es werden beim Einlesen alle Zeilen geprüft, dies funktioniert auch.
Es geht um die letzte Zeile. Bisher war auch die letzte Zeile ein Datensatz. Jetzt wird die Datei mit:

<<File completely written»

beendet. Von der letzten Zeile kommt auch der Fehler bzw. die Fehlermeldung. (Fehler: .... Listenindex außerhalb des Bereiches.)
D.h. es wird hier noch versucht Daten einzulesen, wo keinen mehr sind.

Hänsel
icho2099
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 101
Erhaltene Danke: 12

WIN XP, WIN 7, WIN 10
Delphi 6 Prof, Delphi 2005, FPC
BeitragVerfasst: So 09.05.21 09:46 
wenn die letzte Zeile ein bekannter und konstanter String ist, dann prüfe das doch einfach bevor du die Zeile an die Stringliste verfütterst.
ub60
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 762
Erhaltene Danke: 127



BeitragVerfasst: So 09.05.21 12:10 
Könntest Du die letzte Zeile nicht einfach so abfangen?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
if Pos('File completely written', sZInhalt)=0
  then
    begin
      // Auswertung wie bisher
    end
  else ShowMessage('Ende erreicht');


Um Dir ansonsten weiterzuhelfen, wäre eventuell interessant:
  • Ist die Zeile 1 die einmalig auftauchende Kopfzeile?
  • Ist Zeile 2 eine Datenzeile, die sich (mit anderen Daten mehrfach wiederholt?
  • Welche der Daten brauchst Du genau?

Du könntest dann auch mal noch weiteren Quelltext zeigen, so dass man Dir weiterhelfen kann.
Das, was da oben steht, ist nicht sehr sinnvoll bzw. (wie jaenicke schon geschrieben hat) etwas umständlich.

Ich glaube, dass Du mit ein paar mehr Infos auch mehr Hilfe bekommst.

ub60
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6386
Erhaltene Danke: 146

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Mo 10.05.21 07:33 
Unter der Annahme, dass "echte" Datenzeilen mehr als einen Wert haben, kannst du einfach so vorgehen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
while not EoF(tfDatei) do
begin
  slWerte := TStringList.Create;
  Readln(tfDatei,sZInhalt);
  slWerte.StrictDelimiter := true;
  slWerte.DelimitedText := sZInhalt;
  slWerte.Delimiter :=';';
  slWerte.DelimitedText:=sZInhalt;
  slWerte.QuoteChar := '"';
  slWerte.DelimitedText:=sZInhalt;
  Inc(iZeile); // erste Zeile ist der Kopf

  if slWerte.count > 1 then
  begin               
  //  Einlesung aller Daten
  end;

end;
CloseFile(tfDatei);


Eventuell musst du noch deinen Zähler(iZeile) berücksichtigen.
Blup
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 173
Erhaltene Danke: 43



BeitragVerfasst: Mi 12.05.21 10:50 
Wenn die Stringliste slWerte erzeugt wird, muss sie natürlich auch wieder freigegeben werden.
Die Eigenschaften für das CSV-Format müssen slWerte nur einmal zugewiesen werden.
Den Inhalt der Zeile aus sZInhalt natürlich auch nur einmal je Zeile.

ausblenden volle Höhe 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:
iZeile := 0;

slWerte := TStringList.Create;
try
  slWerte.StrictDelimiter := True;
  slWerte.Delimiter := ';';
  slWerte.QuoteChar := '"';

  while not EoF(tfDatei) do
  begin
    Readln(tfDatei, sZInhalt);
    Inc(iZeile); // erste Zeile ist der Kopf

    if sZInhalt = '«File completely written»' then
    begin
      // letzte Zeile, eventuell Schleife Abbrechen, falls danach noch Zeilen Folgen, die nicht verarbeitet werden sollen
      Break;
    end
    else
    begin
      slWerte.DelimitedText := sZInhalt;
    
      //  Einlesung aller Daten

    end;
  end;
finally
  slWerte.Free;
end;

CloseFile(tfDatei);


Moderiert von user profile iconTh69: Delphi-Tags hinzugefügt
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 12.05.21 14:27 
user profile iconBlup hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
    if sZInhalt = '«File completely written»' then
    begin
      // letzte Zeile, eventuell Schleife Abbrechen, falls danach noch Zeilen Folgen, die nicht verarbeitet werden sollen
      Break;
    end
Das löst das Problem zwar für den konkreten Fall, aber sobald wieder eine Änderung passiert, z.B. wenn dieser Text verändert wird oder eine weitere zusätzliche Zeile hinzu kommt, gibt es wieder ein Problem.

Deshalb ist es sinnvoller das eigentliche Problem auch zu lösen:
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Prüfst du denn die Daten bevor du sie verarbeitest? Oder gehst du vielleicht einfach davon aus, dass eine bestimmte Anzahl von Spalten vorhanden ist?
Wie user profile iconjasocul schon vorgeschlagen hat, sollte schlicht geprüft werden wie viele Spalten eine Zeile hat. Wenn die Anzahl nicht stimmt, ob nun nur eine oder nur 5 statt 6 usw., kann das dann behandelt werden. Natürlich kann man zusätzlich auf den Text prüfen, um diesen bekannten Fall direkt zu behandeln. Aber man sollte beim Import von Daten nie davon ausgehen, dass das Format korrekt ist. Wenn man Fehler gleich richtig behandelt (loggen, melden, ...), findet man das Problem im Fall der Fälle am einfachsten und produziert keine Folgefehler.