AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte TTextStream - Textdateien einlesen
Thema durchsuchen
Ansicht
Themen-Optionen

TTextStream - Textdateien einlesen

Ein Thema von himitsu · begonnen am 19. Mai 2010 · letzter Beitrag vom 4. Nov 2011
Antwort Antwort
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.378 Beiträge
 
Delphi 12 Athens
 
#1

AW: TTextStream - Textdateien einlesen

  Alt 16. Okt 2010, 13:40
Hatte aber noch nicht die Gelegenheit alles zu Testen, darum quasi nur erstmal als PreAlpha, oder so , da es so einige Änderungen gab.

[edit]
Anhang entfernt (Aktuelleres siehe Post #1)
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (18. Okt 2010 um 15:19 Uhr)
  Mit Zitat antworten Zitat
BoolString

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

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
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.378 Beiträge
 
Delphi 12 Athens
 
#3

AW: TTextStream - Textdateien einlesen

  Alt 18. Okt 2010, 13:51
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;
FIndex ist nur ein interner Index, welcher eigentlich extern nix zu suchen hat.
Ich lese die Datei ja blockweise ein, die Zeilen im aktuellen Block werden über FLines indiziert.
FIndex gibt nun an, wieviel von diesem Block schon eingelesen wurde, bzw. an welcher Stelle (Index) man sich dort grade befindet und ob bei einem ReadLine nun noch eine Zeile aus diesem Puffer genommen werden kann, oder ob ein neues Stück geladen+geparst werden muß.

Das mit dem Quote-Zeichen sollte kein Problem sein.

Die Anzahl der Trennzeichen sollte egal sein.
Über das enthaltene TRIM werden mehrere nachfolgene Trennzeichen zusammengefasst.
Ich könnte eventuell aber eine Art StrictDelemiter einführen, wo dann immer nach jedem Leer-/Trennzeichen geteilt und nichts zusammengefaßt wird.

Dieses .ActualRow hat mich noch auf die Idee gebracht, daß man auch noch die Spalte mitzählen könnte, wenn die Zeilen "Value"-weise ausgelesen werden.

Na mal sehn, was sich noch so machen läßt.

[add]
aktuelle Testversion siehe Beitrag #1
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (18. Okt 2010 um 15:22 Uhr)
  Mit Zitat antworten Zitat
Moony

Registriert seit: 29. Jul 2003
Ort: Essen
454 Beiträge
 
Delphi 2010 Professional
 
#4

AW: TTextStream - Textdateien einlesen

  Alt 4. Mär 2011, 14:00
Hallo,

ich habe mir mal deine Klasse runtergeladen und unter Windows XP funktioniert sie. Jetzt habe ich versucht meine Applikation auf einem Windows7 32Bit System zu starten und er kommt an der Stelle zu scheitern, wenn ich versuche den Textstream zu erstellen. Ich rufe folgendes beim Initialisieren auf:

Delphi-Quellcode:
var myFile : TTextStream;
...
myFile := TTextStream.Create(ChangeFileExt(Application.Exename, '.lng'), saRead);
try
  ...
finally
  myFile.Free;
end:
Hoffe auf baldige Hilfe!!!

Danke & Gruß, Moony
Ich weiß, daß ich nichts weiß! Sokrates
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.378 Beiträge
 
Delphi 12 Athens
 
#5

AW: TTextStream - Textdateien einlesen

  Alt 4. Mär 2011, 14:22
Gut, dann erstmal ganz allgemein gefragt:

Wo liegt eine EXE und sicher daß dein Programm dort über ausreichende Zugriffsrechte verfügt?
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Moony

Registriert seit: 29. Jul 2003
Ort: Essen
454 Beiträge
 
Delphi 2010 Professional
 
#6

AW: TTextStream - Textdateien einlesen

  Alt 4. Mär 2011, 14:24
Die Exe liegt in einem Ordner auf dem Desktop. Für diesen User ist bekanntlich in dem Userordner Schreibzugriff drauf.
Ich weiß, daß ich nichts weiß! Sokrates
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.378 Beiträge
 
Delphi 12 Athens
 
#7

AW: TTextStream - Textdateien einlesen

  Alt 4. Mär 2011, 14:39
Gut, bei Win7 war's halt naheliegend, daß es daran liegen könnte, wenn es unter XP noch geht.

Hmmm, wie heißt denn die Fehlermeldung und kannst du zufällig die Zeile nennen, in welcher es knallt?

Eigentlich wäre es sehr ungewöhnlich, wenn es genau in dieser Zeile knallt.
myFile := TTextStream.Create(ChangeFileExt(Application.Exename, '.lng'), saRead); .

Ich glaub die Debuginfos hatte ich zu diesen Units nicht abgestellt, weswegen ich eher glauben würde der Debugger sollte weiter reingehn.
Notfalls mal einen Haltepunkt auf diese Zeile, dann Schritt für Schritt mit F7 weitergehn und die Zeile merken, welche aktiv war, bevor es knallte.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:29 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz