AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

schnelles Textzeilen auslesen ab Position x

Ein Thema von dose · begonnen am 13. Jul 2006 · letzter Beitrag vom 7. Aug 2006
Antwort Antwort
dose

Registriert seit: 12. Jul 2006
11 Beiträge
 
#1

schnelles Textzeilen auslesen ab Position x

  Alt 13. Jul 2006, 21:14
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
http://www.delphifaq.com/faq/f87.shtml
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
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.105 Beiträge
 
Delphi 11 Alexandria
 
#2

Re: schnelles Textzeilen auslesen ab Position x

  Alt 13. Jul 2006, 21:31
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.
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
Benutzerbild von 3_of_8
3_of_8

Registriert seit: 22. Mär 2005
Ort: Dingolfing
4.129 Beiträge
 
Turbo Delphi für Win32
 
#3

Re: schnelles Textzeilen auslesen ab Position x

  Alt 13. Jul 2006, 21:35
Ein array of Byte/Char wäre als Buffer gut geeignet.
Manuel Eberl
„The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.“
- Terry Pratchett
  Mit Zitat antworten Zitat
Hawkeye219

Registriert seit: 18. Feb 2006
Ort: Stolberg
2.227 Beiträge
 
Delphi 2010 Professional
 
#4

Re: schnelles Textzeilen auslesen ab Position x

  Alt 13. Jul 2006, 21:51
Hallo dose,

vielleicht kannst du ja die Unit File64 von himitsu benutzen. Sie enthält u.a. eine Seek-Funktion, die auch mit Textdateien arbeitet.

Gruß Hawkeye
  Mit Zitat antworten Zitat
dose

Registriert seit: 12. Jul 2006
11 Beiträge
 
#5

Re: schnelles Textzeilen auslesen ab Position x

  Alt 7. Aug 2006, 07:20
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;
  Mit Zitat antworten Zitat
Benutzerbild von 3_of_8
3_of_8

Registriert seit: 22. Mär 2005
Ort: Dingolfing
4.129 Beiträge
 
Turbo Delphi für Win32
 
#6

Re: schnelles Textzeilen auslesen ab Position x

  Alt 7. Aug 2006, 08:40
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.
Manuel Eberl
„The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.“
- Terry Pratchett
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#7

Re: schnelles Textzeilen auslesen ab Position x

  Alt 7. Aug 2006, 08:41
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:
{$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;
Grüße vom marabu
Angehängte Dateien
Dateityp: zip textfileutils_491.zip (795 Bytes, 27x aufgerufen)
  Mit Zitat antworten Zitat
dose

Registriert seit: 12. Jul 2006
11 Beiträge
 
#8

Re: schnelles Textzeilen auslesen ab Position x

  Alt 7. Aug 2006, 11:38
Vielen Dank, das ist eine super alternative und wesentlich schneller.

gruß
dose9
  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 01:36 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz