Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi große Textdatei einlesen und filtern (https://www.delphipraxis.net/51141-grosse-textdatei-einlesen-und-filtern.html)

Cakotay 6. Aug 2005 21:48


große Textdatei einlesen und filtern
 
Hallo!
Ich versuche von meinem Browser die Cachedatei(15 mb groß) einzulesen und zu filtern, hab aber das Problem, dass nicht alles abgearbeitet wird (Die Filterung funktioniert aber eben nicht bis zum Ende). Ich wollte das ganze auch in einem Memo anzeigen, habe aber sehr schnell merken müssen, das es damit nicht zurecht kommt. Habe dann davon gelesen das man RichEdit nehmen soll und das hab ich dann auch versucht, allerdings mit der Fehlermeldung :"...Exception der Klasse EOutOfResources aufgetreten. Meldung:'Fehler bei einfügen von RichEdit-Zeile'...".
Das ist allerdings nicht das wichtigste, auf die Anzeige kann ich auch verzichten. Mir geht es eben nur darum das ich meine Informationen aus der Datei bekomme.

Hier mal der Quellcode den ich habe:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
        dateiname           :string;
        datei               :TextFile;
        puffer              :AnsiString;
        puffer2              :AnsiString;
        start               :integer;
        ende                :integer;
begin
        if OpenDialog1.Execute then
        begin
                dateiname := OpenDialog1.FileName;
                try
                AssignFile(datei, dateiname);
                Reset(datei);
                repeat
                        Readln(datei, Puffer);
                        RichEdit1.Lines.Add(Puffer);
                        Puffer2 := Puffer2 + Puffer;
                until EOF(datei);
                while pos('<table width=519>', Puffer2) > 0 do
                begin
                        start := pos('<table width=519>', Puffer2) - 1;
                        delete(Puffer2, 1, start);
                        ende := pos('</table>', Puffer2) + 7;
                        Memo2.Lines.Add(copy(Puffer2, 0, ende));
                        delete(Puffer2, 1, ende);
                end;
                except
                        try
                        CloseFile(datei);
                        except
                        end;
                end;
                CloseFile(datei);
        end;

end;
Würde mich rießig freuen wenn ihr mir da helfen könnt, aber bitte auch so das ich es verstehe, denn Delphi ist nicht gerade mein Spitzengebiet.

Mystic 6. Aug 2005 22:00

Re: große Textdatei einlesen und filtern
 
Benutz doch einen Delphi-Referenz durchsuchenTStringStream.

Cakotay 6. Aug 2005 22:44

Re: große Textdatei einlesen und filtern
 
Danke für die schnelle Antwort aber leider weiß ich nicht wie das geht, wäre schön wenn ihr/du mir das mal näher erklären würdet wie ich dabei vorgehen muss.

glkgereon 7. Aug 2005 08:40

Re: große Textdatei einlesen und filtern
 
hast du ein beispeil für einen datei-teil? ich weiss nämlich nicht so richtig was genau du da filtern willst.

deine methode die datei auszulesen ist aber imho der richtige ansatz

ich würde nur überlegen statt erst alles zu holen und dann zu parsen es "gleichzeitig" zu machen.

so in der art:

Delphi-Quellcode:
var
  start: Integer;
  Puffer: String;
  datei: file;
  StartIn, StopIn, Nimm: Boolean;
begin
  if OpenDialog1.Execute then
    begin
    dateiname := OpenDialog1.FileName;
    try
      AssignFile(datei, dateiname);
      Reset(datei);
      while not EOF(datei) do
        begin
        Readln(datei, Puffer);
        StopIn := pos('</table>', Puffer) <> 0;
        Nimm:=(Nimm or StartIn) and (not StopIn);
        StartIn := pos('<table width=519>', Puffer) <> 0;
        if StartIn then
          begin
          start := pos('<table width=519>', Puffer) - 1;
          delete(Puffer, 1, start);
          Memo2.Lines.Add(Puffer);
          end;
        if StopIn then
          begin
          start := pos('</table>', Puffer) + 7;
          Memo2.Lines.Add(copy(Puffer,0,start));
          end;
        if Nimm then Memo2.Lines.Add(Puffer);
        Puffer:='';
        end;
      CloseFile(datei);
    except
      try
        CloseFile(datei);
      except
      end;
    end;
end;
die frage ist: können die beiden sachen die desucht werden in einer zeile vorkommen können...dann müsste mans noch etwas umbauen...

Cakotay 7. Aug 2005 10:49

Re: große Textdatei einlesen und filtern
 
Ja also in der Datei ist eigentlich alles was so beim Surfen anfällt abgespeichert als HTML-Code manchmal auch CSS und Javascript mit drin und dann auch noch unlesbare Teile. Das ganze ist alles hintereinander geschrieben. Kannste dir ja mal selber anschauen wenn du FireFox als Browser hast. Die Datei liegt unter Anwendungsdaten\Mozilla\FireFox.
Es kommt dort auch vor das die Ergebnisse auf einer Zeile liegen und nicht über mehrere gehen.
Deine Lösung konnte mir leider nicht helfen, der zeigt dann scheinbar wieder die Datei in dem Memo an, bis es eben wieder zu viel für das Memo wird. Mit Richedit kommt dann wieder diese EOutOfResources Meldung.

Cakotay 7. Aug 2005 14:08

Re: große Textdatei einlesen und filtern
 
So ich hab jetzt mal ein wenig mit diesem TStringStream gebastelt und dabei ist der Folgende Code rausgekommen. Das Problem ist jetzt allerdings das sich garnichs tut. Ich hoffe mir kann hier jemand helfen.

Delphi-Quellcode:
var
        dateiname           :string;
        puffer              :TStringStream;
        my_filestream       :TFileStream;
        puffer2              :string;
        start               :integer;
        ende                :integer;
begin
        if OpenDialog1.Execute then
        begin
                dateiname := OpenDialog1.FileName;
                try
                        my_filestream := TFileStream.Create(dateiname, fmOpenread);
                        puffer := TStringStream.Create('');
                        puffer.CopyFrom(my_filestream, my_filestream.Size);
                        my_filestream.Free;
                puffer2 := puffer.ReadString(puffer.Size);
                while pos('<table width=519>', Puffer2) > 0 do
                begin
                        start := pos('<table width=519>', Puffer2) - 1;
                        delete(Puffer2, 1, start);
                        ende := pos('</table>', Puffer2) + 7;
                        Memo2.Lines.Add(copy(Puffer2, 0, ende));
                        delete(Puffer2, 1, ende);
                end;
                except
                end;
            puffer.Free;
        end;

end;

Cakotay 8. Aug 2005 14:43

Re: große Textdatei einlesen und filtern
 
Ich hab es nun endlich hinbekommen das es läuft, ist zwar vielleicht nicht die schnellste Methode aber es läuft. Hier mal der Code falls es jemanden interessiert.

Falls noch jemand eine schneller Möglichkeit einfällt kann er es ja mal posten.

Danke @ Mystic für den Tipp mit TStringStream

Delphi-Quellcode:
var
        dateiname           :string;
        puffer              :TStringStream;
        my_filestream       :TFileStream;
        puffer2              :string;
        start               :integer;
        ende                :integer;
begin
        if OpenDialog1.Execute then
        begin
                dateiname := OpenDialog1.FileName;
                try
                        my_filestream := TFileStream.Create(dateiname, fmOpenread); //Datei in FileStream laden
                        puffer := TStringStream.Create('');
                        puffer.CopyFrom(my_filestream, my_filestream.Size); //Daten aus FileStream in StringStream kopieren
                        my_filestream.Free;
                        puffer.Seek(0, soFromBeginning); //Zeiger auf den Anfang setzen
                        puffer2 := puffer.ReadString(puffer.Size); //StringStream in String laden
                while (pos('<table width=519>', Puffer2) > 0) do //Parsen
                begin
                        start := pos('<table width=519>', Puffer2);
                        ende := pos('</table>', Puffer2) + 7;
                        while ende < start do
                        begin
                                delete(Puffer2, 1, ende);
                                start := pos('<table width=519>', Puffer2);
                                ende := pos('</table>', Puffer2) + 7;
                        end;
                        Memo1.Lines.Add(copy(Puffer2, start, ende - start + 1));
                        delete(Puffer2, 1, ende);
                end;
                finally
                puffer.Free;
                my_filestream.Free;
                end;
        end;

end;
EDIT: habe wie einen Beitrag weiter unten empfohlener Weise aus dem "try..except..end"-Block einen "try..finally..end"-Block gemacht. Ausserdem hab ich noch einen kleinen Fehler gemerkt und ausgebessert (die Endposition kann vor der Startposition liegen). Ist jetzt denke ich mal mit der zusätzlichen while ... do behoben.

Thanatos81 8. Aug 2005 15:08

Re: große Textdatei einlesen und filtern
 
Ich würde aus deinem "try..except..end"-Block einen "try..finally..end"-Block machen und dort das my_filestream.free und puffer.Free einbauen, damit der Speicher für die beiden Objekte auf jeden Fall wieder freigegeben wird und dein Prog kein Memoryleak produziert.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:43 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