![]() |
schnelles Textzeilen auslesen ab Position x
Hallo Delphi'ler
Leider muß ich gleich meinen ersten Beitrag als Frage formulieren, aber ich verspreche Besserung. Ich habe über die Suchfunktion eine ganze Reihe Beiträge gefunden die sich mit dem Zeilenweisen auslesen von Dateien beschäftigen. Leider muß ich ein existierendes Dateiformat öffnen und ab Position x im File anfangen zu lesen ohne vorher das gesamte File durchlaufen zu müssen (Also Datei binär zugreifen und Seek-Komando...). Die Dateien sind teilweise relativ groß 100-200 MB, weshalb zum Beispiel das Einlesen in eine TStringlist ausscheidet. Das ganze soll natürlich sehr effektiv und schnell erfolgen. Ich habe es bereits kurz zusammen programmiert über den Zugriffstyp binär mit "File of Byte" zeichenweise jedes Byte ausgelesen und exemplarisch in ein Datenfeld zu schreiben, jedoch war die Geschwindigkeit sehr langsam. Beim Suchen im Internet habe ich diese Seite gefunden ![]() die ungefähr das realisiert was ich möchte nur eben verkehrt. Daher 2 Fragen: 1. Was mache ich grundsätzlich falsch wenn ich zeichenweise die Daten auslese? Warum ist ein Buffer effektiver? 2. Wie realisiere ich so etwas prinzipiell, da ich ja das Zeilenende erst mit dem chr(13) bzw. (10) erkenne? Viele Grüße ...und danke für den Fisch... dose |
Re: schnelles Textzeilen auslesen ab Position x
Moin Dose,
erst einmal herzlich willkommen hier in der Delphi-PRAXiS. Wenn Du nicht byteweise durchgehst, sondern einen Buffer verarbeitest, kannst Du selber bestimmen, wie gross der Buffer ist, denn ein Buffer wird intern auf jeden Fall angelegt (ich weiss jetzt allerdings nicht wie gross). Wenn Du es mit TFileStream machst, könntest Du die Stelle aber der Du lesen willst direkt mit der Eigenschaft Position angeben. Ab dieser Stelle füllst Du Deinen Buffer und verarbeitest ihn. Dies dann so lange, bis Du das gewünschte gefunden, oder alles gelesen hast. Da Du ja offensichtlich nicht nur Strings in der Datei hast (sonst könntest Du ja einfach zeilenweise lesen), stellt sich mir die Frage, ob Du nicht eventuell auch Records verwenden könntest um die Nicht-Strings zu lesen. |
Re: schnelles Textzeilen auslesen ab Position x
Ein array of Byte/Char wäre als Buffer gut geeignet.
|
Re: schnelles Textzeilen auslesen ab Position x
Hallo dose,
vielleicht kannst du ja die ![]() Gruß Hawkeye |
Re: schnelles Textzeilen auslesen ab Position x
Hallo,
Vielen Dank für die Tips. Ich habe mir die Unit File64 angeschaut, aber leider funktionieren dort die Positionszeiger nicht so ganz sauber wie ich mir das vorstelle. Daher möchte ich das lieber auf 32 bit realisieren. Anbei mein Code, der eine Datei durchforstet und jeweils bei CrLf eine neue Zeile ausgibt. (Siehe Ausgabe). Ich habe trotzdem das Gefühl dass das nicht sonderlich Performant (vermutlich zuviele Variablenzuweisungen) ist, bzw. teilweise sogar nicht sauber funktioniert. (wenn Startposition und Endposition nicht die gesamte Datei beinhalten). Prinzipiell arbeitet der Code so, dass der den Buffer dessen größe in MAXLINELENGTH festgelegt wird in eine Variable ließt und untersucht. Der Rest nach dem Zeilenumbruch wird dann in die Variable Linebuffer übernommen und die Abarbeitung beginnt von neuem. Habt jemand von euch noch einen optimierungs Tip? Ich wäre sehr dankbar.
Delphi-Quellcode:
const
MAXLINELENGTH = 128; FileName = 'c:\in.file'; var curr, feof, readlen, tmppos: Longint; startpos, Stoppos: Longint; Buffer : array [0..MAXLINELENGTH] of char; p : PChar; f : integer; Line : string; LineBuffer : string; text : string; begin f := FileOpen (FileName, 0); feof := FileSeek (f, 0, 2); // feof = Größe der Datei (wo das Lesen Startpos := 0; // Startpos setzt den Dateizeiger dorthin wo das Einlesen begonnen werden soll Stoppos := feof; // Wir wollen jetzt mal exemplarisch die gesammte Datei bearbeiten... FileSeek (f, 0, 0); // Dateizeiger an den Anfang der Datei curr := FileSeek (f, 0, 1); // Aktuelle Position in curr einlesen LineBuffer := ''; while (curr < stoppos do begin if ((curr + MAXLINELENGTH )> stoppos then begin readlen := stoppos- curr; end else begin readlen := MAXLINELENGTH; end; FileRead(f, Buffer, readlen); p := StrScan (Buffer, #10); if p = Nil then begin if (StrScan (Buffer, #13) = Nil) then begin Line := Copy(Buffer,0,MAXLINELENGTH); end else begin Line := Copy(Buffer,0,MAXLINELENGTH-1); end; LineBuffer := LineBuffer + Line; end else begin Line := Copy(Buffer,0,(p-@Buffer-1)); text := LineBuffer + Line; LineBuffer := ''; FileSeek (f, 0-readlen+(p-@Buffer)+1, 1); Memo1.Lines.Add(text); // Exemplarische Ausgabe end; curr := FileSeek(f, 0, 1); end; FileClose (f); end; |
Re: schnelles Textzeilen auslesen ab Position x
Ich glaube recht viel performanter wirst dus nicht hinkriegen - eine Festplatte hat halt immer noch Zugriffszeiten im Millisekundenbereich, ein Prozessor verarbeitet deinen Code im Mikrosekundenbereich.
Das heißt die Festplatten sind einfach zu langsam für sowas. |
Re: schnelles Textzeilen auslesen ab Position x
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo.
TextFile ist zwar ein alter Hut, aber wenn es dich nicht stört, dann kannst du die darin enthaltene Puffertechnik verwenden und bequem mit ReadLn und WriteLn auf die Textzeilen zugreifen. Wenn ich beim Anpassen meiner alten TP-Quellen keinen Fehler gemacht habe, dann funktioniert prinzipiell das hier:
Delphi-Quellcode:
Grüße vom marabu
{$I Func.TextFilePos.pas}
{$I Func.TextFileSeek.pas} procedure ReadLines(const fn: TFileName; startPos, numLines: Cardinal; s: TStrings); var tf: TextFile; line: String; begin AssignFile(tf, fn); Reset(tf); // SetTextBuf() hier, wenn nötig TextFileSeek(tf, startPos); while not Eof(tf) and (s.Count < numLines) do begin ReadLn(tf, line); s.Add(line); end; CloseFile(tf); end; procedure TDemoForm.ButtonClick(Sender: TObject); begin with OpenDialog do if Execute then ReadLines(FileName, 1, 1, Memo.Lines); end; |
Re: schnelles Textzeilen auslesen ab Position x
Vielen Dank, das ist eine super alternative und wesentlich schneller.
gruß dose9 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:26 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