Einzelnen Beitrag anzeigen

BoolString

Registriert seit: 2. Feb 2009
Ort: Varel
70 Beiträge
 
RAD-Studio 2009 Pro
 
#30

AW: TTextStream - Textdateien einlesen

  Alt 18. Okt 2010, 09:47
Hallo Himitsu,

habe am Wochenende mal deine Neuerungen getestet. Die Probleme scheinen sich jetzt gelöst zu haben.

Ganz klar ist mir allerdings noch nicht was intern mit deinem fIndex passiert. Ich habe diese Variable mal als Property ActualRow in tTextStream nach außen gelegt:
Property ActualRow: Integer Read fIndex Write fIndex; Das funzt auch. Der Vorteil ist (aus meiner Sicht), daß man den Zeiger auf eine beliebige Stelle innerhalb der Datei setzen kann. Es ermöglicht, z.B. bei der Verwendung in einem Import-Wizard, daß man die Datei neu parsen kann, wenn irgendwelche Einstellungen verändert werden sollen. Neben der aktuellen Zeile hat man dann auch gleichzeitig noch die Angabe wie viele Zeilen (mit Wiederholungen) überhaupt schon verarbeitet wurden über f.GetProcessedLines.

Soweit ich das richtig verstanden habe ist fIndex ein Null-basierter Index, der in fLines verwendet wird. Nutze ich das mit dem folgenden Code:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
Var f: tTextStreamEx;
     aFile : String;
     astring : UnicodeString;
     aRunner : Integer;
     aString2: String;
     aString3: UnicodeString;
     aBytes : tBytes;
     aSize : Integer;
     aLineNo : String;
begin

aFile := 'C:\Users\D. Jan Schulz\Desktop\Iris-Tab - Kopie UTF8.txt';

F := TTextStreamEx.Create(aFile, saRead);
Try
  Memo1.Clear;
  aBytes := f.Encoding.GetPreamble;
  Memo1.Lines.Add('Byte sequence:' + PWidechar(aBytes));
  aString2:= f.Encoding.ToString;
  Memo1.Lines.Add('BOM code: ' + aString2);
  Memo1.Lines.Add(IntToStr (ord (f.LineBreak))) ;
  aSize := f.CRLFCounter;
  Memo1.Lines.Add('CRLF count: ' + IntToStr(aSize));
  aSize := f.LFCounter;
  Memo1.Lines.Add('LF count: ' + IntToStr(aSize));
  aSize := f.CRCounter;
  Memo1.Lines.Add('CR count: ' + IntToStr(aSize));


  f.ActualRow := 0; // Unterschied, wenn diese Zeile auskommentiert ist

  While not f.EoF do Begin
      aLineNo := IntToStr(f.ActualRow) + '/'+IntToStr(f.GetProcessedLines) + ': ';
      aString := f.ReadLine;

      Memo1.Lines.Add(aLineNo + aString+ '-> '+ IntToStr(f.ActualRow) + '/'+IntToStr(f.GetProcessedLines));
  End;

Finally
  F.Free;
End;
end;
Bekomme ich die erste Zeile zwei mal, wobei GetProcessedLines schon vorher auf 1 steht und sich von fLines unterscheidet.
Kommentiere ich im obigen Beispiel die markierte Zeile aus, habe ich eine korrekte Auslesung und beide Werte sind identisch (ebenso als wenn ich f.ActualRow auf 1 setze). Ist der doch nicht Null-basiert?


Zusätzlich ist mir aufgefallen, daß du offensichtlich feste Delimiter verwendest. Oftmals wird aber auch das Leerzeichen genutzt oder irgendwelche mystischen Symbole. Dadurch ist deine Arbeit mit den schönen ReadValues nur bedingt universell.

Das gleiche gilt für Quote-Zeichen. Hier wird neben " auch oftmals ' verwendet oder irgendwas anders (hab schon mal ein @ gesehen). Aus dem Grund wäre es sicherlich gut, wenn man dies Zeichen frei definieren kann.

Was in der Praxis auch schwierig ist, ist die Tatsache, daß ein ReadValue sofort eine Exception wirft, sobald ein falsches Format vorliegt. Hier wäre sicherlich noch eine weitere Funktion sinnig, die einen Wert zurückgibt, der nach den Ländereinstellungen des Rechners umgeschrieben wurde (Dateien mit Komma als Dezimaltrenner, aber mit Punkt auf dem Zielrechner) und einfach den ausgelesenen String, wenn die Wandlung nicht möglich war (z.B. ein Datum, Zeit, Kommentar oder ähnliches).
Oftmals benötigt man die Daten weiterhin als String, aber hätte gerne die Formatierung auf das aktuelle System umgeschrieben. Besonders in gemischten Dateien.

Jan

PS: Ich hab mal vorsichtshalber meine Testdatei angehängt. Es ist der klassiche Iris Datensatz mit einer UTF8-Präambel.

PPS: Sicherlich sind einige Anmerkungen nur relativ selten vorkommende Fälle. Wenn man aber viel mit solchen Daten zu tun hat, dann stolpert man sehr häufig über solche Sonderfälle. Stell dir mal vor ein Amerikaner und ein Russe (mit jeweils eigenen Ländereinstellungen) erzeugen Daten und migrieren diese auf einem Rechner, der eine deutsche Ländereinstellung verwendet. Lustige Kombinationen von Dezimal- & Tausendertrennzeichen sind die Folge, ebenso wie Datumswerte...
Teilweise werden auch Mehrere Trennzeichen (z.B.) Space hintereinander geschrieben, die man dann als ein zeichen interpretieren muss. Und dabei meine ich KEINE festen Spaltenbreiten. z.B. immer 4 Space Zeichen, und dann die Werte/Informationen in unterschiedlicher Länge...
Angehängte Dateien
Dateityp: zip Iris-Tab - Kopie UTF8.zip (1,2 KB, 12x aufgerufen)
  Mit Zitat antworten Zitat