AGB  ·  Datenschutz  ·  Impressum  







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

Problem mit großer Textdatei

Ein Thema von PeSch · begonnen am 9. Jan 2012 · letzter Beitrag vom 12. Jan 2012
Antwort Antwort
Seite 1 von 2  1 2      
PeSch

Registriert seit: 9. Jan 2012
6 Beiträge
 
#1

Problem mit großer Textdatei

  Alt 9. Jan 2012, 16:58
Hallo Leute,

Bin neu im Forum und weiss nicht ob ich hier in der richtigen Kategorie bin.

Vorab: Suchfunktion habe ich schon benutzt, was ich gefunden habe reicht mir nicht .

Folgendes Problem: ich habe eine sehr große Text-Datei (.txt) (rund 260MB), die ich durchsuchen will. Im wesentlichen enthält die abermillionen von Zeilen mit Messdaten und zwischendrin immer mal einige Strings wie bspw. "Frame". Nach jenen möchte ich suchen und mir die Zeile ausgeben lassen in der Sie sich befinden. Wie lange die Suche dauert bzw. wie effizient sie ist, spielt für mich keine Rolle. Obs nun 5min oder 20min dauert, völlig egal, hauptsache ich muss nichts per Hand machen .

Der Code:

Code:
var
Dateipfad: String;
FrameNumber,i,j: Integer;
Datensatz :TStringList;
Positionen: Array of Integer;
Abstaende: Array of Integer;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
    FrameNumber:=StrToInt(Edit2.text);
    Dateipfad:=Edit1.text;
    Datensatz:=TStringList.create;
    Datensatz.LoadFromFile(Dateipfad);
    SetLength(Positionen,FrameNumber+1);

    For i:=1 To Datensatz.Count-1 Do
        Begin
           If Pos('Frame',Datensatz.Strings[i])>0 Then
           Begin
           Positionen[i]:=i;
           ListBox1.Items.Add(IntToStr(Positionen[i]));
           End;
        end;


    Datensatz.free;
end;

end.
Was ich in eurer Hilfe und im Forum schon gelesen habe, ist dass TStringList nicht grad die effizienteste und eleganteste Lösung ist, aber die am einfachsten verständliche und das reicht mir vollkommen. Nun zum Problem: Der Code funktioniert bei kleineren Dateien einwandtfrei, bspw bei 15MB. Bei den großen kommt immer eine Fehlermeldung nach gewisser Zeit, warum weiss ich nicht. Wenn die Fehlermeldung kommt wird das Programm im Arbeitsspeicher RIESIG...das nimmt erst alle paar Sekunden um ca 50MB zu, bis die Größe der Text-Datei erreicht ist + Eigengröße. Dann tut sich eine Zeit lang nichts und dann explodiert die Größe im RAM auf etwas über 1GB und dann kommt der error: "Access violation". Ich nutze Lazarus, hoffe das ist im Delphi-Forum kein Problem.


Wäre wirklich froh, wenn mir jemand helfen könnte.

MfG

Peter


P.S.: Das Problem hängt nicht vom OS ab, tritt bei Win7 und WinXP auf.
  Mit Zitat antworten Zitat
Benutzerbild von implementation
implementation

Registriert seit: 5. Mai 2008
940 Beiträge
 
FreePascal / Lazarus
 
#2

AW: Problem mit großer Textdatei

  Alt 9. Jan 2012, 17:08
Wenn du über eine TStringList eine Datei lädst, dann liegt diese natürlich komplett im Speicher.
Ist die Datei also 2 GiB groß, sind damit auch 2 GiB RAM gleich weg.
Um solche gewaltigen Größen zu verarbeiten, solltest du immer nur einen Teil der Datei im Speicher halten.
Dies ginge bspw. mit TFileStream , System.Text (=SysUtils.TextFile, aber <>SysUtils.Text, aufpassen!) oder file of char .
Diese kannst du nun Zeile für Zeile auslesen, und jede Zeile einzeln durchsuchen.

[EDIT]
Btw., willkommen in der DP!

Geändert von implementation ( 9. Jan 2012 um 17:33 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#3

AW: Problem mit großer Textdatei

  Alt 9. Jan 2012, 17:08
Streams, oder in Deinem Fall etwas in der Art:
Delphi-Quellcode:
var
  f:TextFile;
  s:String;
begin
  AssignFile(f,<DateiMitPfad>);
  Reset(f);
  while not EOF(f) do
    begin
    Readln(f,s);
    TuWas;
    end;
 CloseFile(f);
end;
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: Problem mit großer Textdatei

  Alt 9. Jan 2012, 17:09
Beim nächsten Mal bitte die Delphi-Tags nutzen

Delphi-Quellcode:
var
  Dateipfad : String;
  FrameNumber, i, j : Integer;
  Datensatz : TStringList;
  Positionen : Array of Integer;
  Abstaende : Array of Integer;

  { TForm1 }

procedure TForm1.Button1Click( Sender : TObject );
begin
  FrameNumber := StrToInt( Edit2.text );
  Dateipfad := Edit1.text;
  Datensatz := TStringList.Create;
  Datensatz.LoadFromFile( Dateipfad );
  SetLength( Positionen, FrameNumber + 1 );

  For i := 1 To Datensatz.Count - 1 Do
    Begin
      If Pos( 'Frame', Datensatz.Strings[i] ) > 0
      Then
        Begin
          Positionen[i] := i; // hier könnte ein Überlauf passieren, wenn i > FrameNumber
          ListBox1.Items.Add( IntToStr( Positionen[i] ) );
        End;
    end;

  Datensatz.Free;
end;

end.
  1. Du prüfst niemals nach, ob das Array Positionen noch Platz hat
  2. Das Array hat beim Befüllen "Löcher", da ja wohl nicht in jeder Zeile das Wort "Frame" zu finden ist
  3. Das Befüllen der ListBox dauert hier auch seine Zeit, da bei jedem Einfügen die ListBox wieder neu gezeichnet wird
    Abhilfe schafft
    Delphi-Quellcode:
    ListBox.Items.BeginUpdate;
    try
      // ListBox mit allem Möglichen füllen
    finally
      ListBox.Items.EndUpdate;
    end;
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 9. Jan 2012 um 17:12 Uhr)
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.768 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: Problem mit großer Textdatei

  Alt 9. Jan 2012, 17:12
Hallo,

du könntest die Datei auch zeilenweise durchgehen.
Delphi-Quellcode:
var
  data: Textfile;
  i : Integer;
  s : ansiString;

begin
 ..
 Assign(datei,'dateiname');
 reset(datei);
 i:=0;

 while not eof(datei) do
   begin
     readLn(datei,s),
     inc(i);
     if {frame in s enthalten} then
       begin
         // tuwas
       end;
   end;
  close(datei);
end;
Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#6

AW: Problem mit großer Textdatei

  Alt 9. Jan 2012, 17:16
[QUOTE=PeSch;1145074]
Delphi-Quellcode:
    SetLength(Positionen,FrameNumber+1);

    For i:=1 To Datensatz.Count-1 Do
        Begin
           If Pos('Frame',Datensatz.Strings[i])>0 Then
           Begin
           Positionen[i]:=i;
           ListBox1.Items.Add(IntToStr(Positionen[i]));
           End;
        end;
Wofür das gut sein soll,verstehe ich nicht.
Du hast eine FrameNumber, die Du nutzt um die Größe von Postionen zu definieren.

Dann trägst Du in Positionen die Zeilennummer ein, in der "Frame" gefunden wurde.
Da wäre es wesentlich sinnvoller SetLength(Positionen,Datensatz.Count); zu verwenden.

Und warum löschst Du die Zeilen die "Frame" enthalten nicht gleich?
Delphi-Quellcode:
for i:=Datensatz.Count-1 downto 0 do
  if pos('Frame',Datensatz[i])>0 then Datensatz.Delete[i];
Gruß
K-H

Roter Kasten auf Urlaub in Österreich?
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector

Geändert von p80286 ( 9. Jan 2012 um 17:19 Uhr)
  Mit Zitat antworten Zitat
generic

Registriert seit: 24. Mär 2004
Ort: bei Hannover
2.416 Beiträge
 
Delphi XE5 Professional
 
#7

AW: Problem mit großer Textdatei

  Alt 9. Jan 2012, 17:31
Willst du das unbedingt programmieren?

Wenn nicht, dann schau dir mal das Programm GREP an.
Gibt es auch für Windows!
Coding BOTT - Video Tutorials rund um das Programmieren - https://www.youtube.com/@codingbott
  Mit Zitat antworten Zitat
PeSch

Registriert seit: 9. Jan 2012
6 Beiträge
 
#8

AW: Problem mit großer Textdatei

  Alt 9. Jan 2012, 19:11
Hallo Leute,


Vielen Dank für die Vielen Antworten, das ging ja blitzschnell .

@K-H:
Vielleicht erstmal zur Erklärung woher das ganze kommt: Also die Anzahl der "Frames" ist mir bekannt, löschen will ich sie erst in einem zweiten Schritt mit einem weiteren Button (aber vielen Dank für den Code, weil ich hab das bis letzte Woche per Hand gemacht, und das ist echt nervig ). Der Ursprung des Ganzen ist eine CAD PIC Plasmasimulation. Diese erzeugt nach jedem Zeitschritt (Frame) eine Tabelle von ca 20*250.000 Positionen und Geschwindigkeiten. In dieser Tabelle sind die Zeitschritte eben durch das Wort "Frame" getrennt. Warum ich die Positionen der ZEILEN wissen möchte: Leider sind nicht alle Frames gleich lang. Nach einer gewissen Zeit verlassen einige der Macropartikel die Numerical Domain der Simulation und somit ändert sich die Anzahl der noch vorhandenen Teilchen pro Frame. Um eine Teilchentrajektorie in der Liste verfolgen zu können muss aber die Länge jedes Frames bekannt sein (= Differenz der Positionsnummern zweier aufeinanderfolgender Frames). Daher der ganze Aufwandt.

@generic:
Programmieren wollte ich das selbst, weil ich dann noch sehr vieles andere im Programm implementieren kann (Analytische Modell etc.) und es kann ja nicht schaden, ein wenig Programmieren zu üben (bin ziemlich eingerostet seit der Schule).

Zurück zur Sache:
@Sir Rufo: Danke schön, werde den Code morgen optimieren.

@Klaus und Bummi:
Das könnte funktionieren, werde ich gleich morgen mal ausprobieren! Vielen Dank! (soweit ich das sehen kann habt ihr ja ziemlich genau das gleiche vorgeschlagen, das wäre denke ich die sauberste Lösung von allen). Ich hatte auch mal überlegt das so ähnlich zu machen (hatte das in der Forumssuche gefunden) war nur nicht ganz sicher ob das Zeilenbehaftet funktioniert, sprich: Zu Beginn hatte ich einen Stream in ein String geladen, da hat er mir aber dann die Zeichenposition gegeben, die ich natürlich nicht gebrauchen kann. Zeilenweise abtasten hört sich sehr gut an.

Ich werds mal ausprobieren und morgen melde ich mich wieder um zu berichten.

Vielen Dank!!!!

P.S.: Was ist eigentlich mit Delphi passiert? Ich hab das viele Jahre nicht gemacht, dann im Studium wieder gebraucht, aber gefunden habe ich nur noch Lazarus. Gibts kein Delphi mehr? Früher gabs doch dieses Personal 6 für Schüler und Studenten kostenlos.

Mit freundlichen Grüßen

Peter
  Mit Zitat antworten Zitat
PeSch

Registriert seit: 9. Jan 2012
6 Beiträge
 
#9

AW: Problem mit großer Textdatei

  Alt 10. Jan 2012, 11:32
Hallo Leute,

Sorry für den Doppel-Post.

Also erstmal Vielen Dank an alle, ihr habt mir sehr geholfen.

Ich habe das Programm nun so abgeändert, wie Klaus und Bummi vorgeschlagen haben und zusätzlich optimiert wie von Sir Rufo vorgeschlagen.

Es funktioniert tadellos und auch recht schnell! Ich habe das Programm dann so erweitert, dass es mir zusätzlich eine neue Datei erstellt, in der nur noch die reinen Daten vorhanden sind und alle Störzeilen wegfallen. Des weiteren erstellt das Programm auch noch eine kleine Datei in der die Intervalllängen eingetragen sind, sodass ich die da ablesen kann.

Dadurch kann ich meine Daten nun grade zu in Fliessbandarbeit auswerten .

VIELEN DANK!!!!


Eine Anmerkung noch: Inc() finde ich überflüssig wie einen Kroppf. Früher ging das einfach via i:=i+1; ...


Eine Frage hätte ich noch:

Was ist denn der gravierende Unterschied zwischen ANSISTRING und STRING? Ich hab hier im Forum irgendwo mal gelesen das wäre nur eine reine Umbennenung in neueren Versionen?!

MfG


Peter
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

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

AW: Problem mit großer Textdatei

  Alt 10. Jan 2012, 11:48
Inc(i) und i:=i+1 ist das Gleiche.
Was der Programmierer nutzt, ist ihm überlassen und der Compiler optimiert am Ende alles in ein INC (Assembler).


String und Char sind keine statischen Datentypen.
Die passen sich an den Compiler die kompilierte Zielumgebung an.
Seit Delphi 2009 ist String=UnicodeString und davor AnsiString.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 12:14 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