Einzelnen Beitrag anzeigen

alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#31

Re: CSV-Reader. Schnelles lesen von CSV-Dateien

  Alt 10. Aug 2009, 08:38
Hallo Jan,
Das von Dir beschriebene Datenformat (konstante Spaltenbreite) sind nicht nur keine CSV-Datei "im eigentlichen Sinne", sondern überhaupt nicht.

Um Daten mit konstanter Spaltenbreite zu importieren, sollte sich ein anderer Reader implementieren lassen, der dies wesentlich eleganter und vor allem performanter lösen kann: Er benötigt ja nur die Spaltenbreite, den linken Abstand sowie optional ein Füllzeichen. So ein Reader funktioniert intern völlig anders als ein CSV-Reader, wieso sollte man also einen CSV-Reader dafür 'aufwerten' (ich würde das eher 'verwässern' nennen)? Eine Klasse sollte genau einem Zweck dienen (hier: Lesen von CSV-Dateien).

Zudem sollte man Klassen auch nicht mit Eigenschaften ausstatten, deren Funktionalität sich mit wenigen Aufrufen der Elementaroperationen selbst nachbilden lässt:

Nur leere Zellen am Anfang der Zeile ignorieren:
Delphi-Quellcode:
Var
  bAtBeginningOfLine : Boolean;
  iRealColumn : Integer;
  sCellData : String;
...
csvReader.First;
While not csvReader.Eof Do Begin
  bAtBeginningOfLine := True;
  iRealColumn := 0;
  For i := 0 to csvReader.ColumnCount - 1 Do Begin
    sCellData := csvReader.Columns[i];
    If bAtBeginningOfLine And (sCellData = '') Then Continue;
    bAtBeginningOfLine := False;
    inc (iRealColumn); // Die 'Spaltennummer' ohne leere Zellen am Anfang
    Memo.Lines.Add (sCellData);
  End;
  csvReader.Next;
End;
Leere Zellen ignorieren:
Delphi-Quellcode:
Var
  iRealColumn : Integer;
  sCellData : String;

...
csvReader.First;
While not csvReader.Eof Do Begin
  iRealColumn := 0;
  For i := 0 to csvReader.ColumnCount - 1 Do Begin
    sCellData := csvReader.Columns[i];
    If sCellData = 'Then Continue;
    inc (iRealColumn); // Die 'Spaltennummer'
    Memo.Lines.Add (sCellData);
  End;
  csvReader.Next;
End;
Die OOP-konforme Vorgehensweise hier (für Dich) wäre so:
1. Definieren einer abstrakten Basisklasse ("TableReader"), die die elementaren Operationen zum Lesen von Daten aus Dateien bereitstellt (First, ColumnCount, Next, Eof, Columns).
2. Umschreiben der Klasse CSV-Reader als Nachfolger des "TableReader".
3. Implementieren der Klasse "Constant-Column Reader" als Nachfolger des "TableReader".

Du kannst nun auch weitere 'TableReader' implementieren, z.B. die eine SYLK-Datei einlesen, oder direkt mit BIFF arbeiten, oder XML, JSON etc. Der Vorteil ist, das Du diverse schlanke, wartbare und performante Klassen hast, die ohne Probleme erweiterbar und optimierbar sind. Bei einer eierlegenden Wollmilchsauklasse ("God Class") ist dies nicht der Fall.

Gruß zurück.
  Mit Zitat antworten Zitat