Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Große Textdateien verarbeiten (https://www.delphipraxis.net/159661-grosse-textdateien-verarbeiten.html)

-187- 7. Apr 2011 08:54

Große Textdateien verarbeiten
 
Moin,

ich weiss das es schon unzählige Male diskutiert wurde, jedoch wurden in vielen Beiträgen keine Alternativ-Lösungen diskutiert.

Sagen wir ich habe eine Textdatei (500 MB, durchaus möglich) und möchte diese jetzt verarbeiten.
Von Klaus habe ich diese Lösung in einem anderen Thread gefunden, jedoch ist das immernoch zu langsam.

Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  F:TextFile;
  tmp : String;
begin
  If OpenDialog1.Execute Then
    Begin
    AssignFile(F,OpenDialog1.Filename);
    Reset(F);
    while not eof(F) do
      begin
       Readln(F,tmp);
       // mache etwas mit tmp
      end;
    CloseFile(F);
  end;
end;
Wie würdet ihr an diese Problemstellung rangehen ?

Lemmy 7. Apr 2011 09:00

AW: Große Textdateien verarbeiten
 
Hi,

ich denke "mache was mit tmp" ist hier schon entscheidend... Und was bedeutet "..jedoch ist das immernoch zu langsam.."? Ist hier "mache was mit tmp" das Problem? Oder ist zu wenig Speicher verfügbar um die 500MByte zu laden? IN dem Fall könnten Streams die Lösung sein....

Grüße

p80286 7. Apr 2011 09:12

AW: Große Textdateien verarbeiten
 
Zitat:

Zitat von -187- (Beitrag 1093575)
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  F:TextFile;
  tmp : String;
  buffer : array [0..16383] of byte;
begin
  If OpenDialog1.Execute Then
    Begin
    AssignFile(F,OpenDialog1.Filename);
    settextbuffer(F,buffer);
    Reset(F);
    while not eof(F) do
      begin
       Readln(F,tmp);
       // mache etwas mit tmp
      end;
    CloseFile(F);
  end;
end;
?

Das sollte ein wenig schneller sein.

Gruß
K-H

jfheins 7. Apr 2011 09:22

AW: Große Textdateien verarbeiten
 
Datei aus dem Filestream in einen Memorystream (oder Array oder ...) kopieren und dann dort arbeiten - der Kopiervorgang dauert vielleicht ein wenig (10 Sekunden) aber danach sollte das Arbeiten auf den Daten schnell sein ;)

Falls das jetzt daneben war: Was sind die Anforderungen: Möglichst schnell anfangen zu lesen? Möglichst wenig Speicher verbrauchen?

himitsu 7. Apr 2011 09:59

AW: Große Textdateien verarbeiten
 
Das Laden einer 500 MB AnsiDatei, in eine TStringList, kann schonmal über 1,5 GB RAM benötigen, wobei am Ende 1 GB an Unicode im Speicher verbleibt ...
das könnte schonmal ein bissl eng werden (außer man nutzt Delphi XE2 :stupid:)

http://www.delphipraxis.net/159628-d...ml#post1093342

-187- 7. Apr 2011 10:15

AW: Große Textdateien verarbeiten
 
Hmm aufgrund eurer Posts habe ich nochmal überlegt.. Eigentlich liegt mein Schwerpunkt nicht auf "Schnelligkeit" sondern auf "Wenig Speicher" - Jedoch am besten beides, bzw ein gesundes Mittelmaß finden :)

Es ist durchaus möglich das ich auch mal eine 1 GB Datei habe.

idefix2 7. Apr 2011 10:26

AW: Große Textdateien verarbeiten
 
Und wo liegt das Problem beim ersten von Dir geposteten Ansatz - wenn due die Datei zeilenweise einliest, ist es egal, wie gross sie ist, der Bedarf an Arbeitsspeicher ist vernachlässigbar klein, es braucht ja nur eine Zeile gleichzeitig im Speicher zu sein.

Der Vorschlag von k-h, einen Textpuffer einzuführen, wird den Lesevorgang selbst deutlich beschleunigen, auch ein deutlich grösserer Textpuffer sollte bei einem halbwegs aktuellen Rechner speichermässig verkraftbar sein. Ob das wirklich insgesamt etwas merkliches bringt, hängt davon ab, was Du dann mit den Daten machst, und wie lange die Bearbeitung sonst braucht.

Entscheidend ist überhaupt, was Du mit den Daten machst. readln ist sinnvoll, wenn Du die Daten zeilenweise verarbeitest, andernfalls kann es günstiger und vor allem schneller sein, die Daten blockweise in den Speicher zu holen und vielleicht direkt in einem array of char zu fuhrwerken - aber das kann man eben nur sagen, wenn man weiss, worin genau die Verarbeitung der Daten besteht - readln gehört sicher nicht zu den schnellsten Routinen, dafür bekommst Du die Daten eben schön zeilenweise serviert.

Deep-Sea 7. Apr 2011 10:30

AW: Große Textdateien verarbeiten
 
@-187-:
Wenn du für jede Zeile - und ich denke mal, dass es viele sind - Windows-API-Funktionen bemühst, sinkt die Verarbeitungsgeschwindigkeit rapide. Da ändert auch ein TFileStream nichts.
Ich habe mir mal Klassen zur Verarbeitung von JSON-Dateien geschrieben. Die waren ebenfalls extrem langsam, bis ich mir einen eigenen Puffer angelegt habe. :-D

himitsu 7. Apr 2011 10:33

AW: Große Textdateien verarbeiten
 
Es gibt schon einen Textpuffer, aber der ist "nur" 128 Byte klein und um effektiv zu sein, sollte er am besten ein Mehrfaches der Sektor-Größe, bzw. besser noch der Cluster-Größe des Datenträgers entsprechen und mindestens 4 KB (16, 32 oder 64 KB haben sich da als durchschnittlich gute Werte erwiesen).

-187- 7. Apr 2011 11:02

AW: Große Textdateien verarbeiten
 
Hmm im Grunde möchte ich mit einer Schleife mehrere Dateien in einem Memo aneinander hängen.
Wenn ich die Datei jedesmal direkt dem Memo hinzufüge habe ich Geschwindigkeits Probleme. (Memo=VCL)

Wenn ich die Dateien erstmal in einer StringListe zusammenfüge und am Ende mit "Memo1.Text:=sl.Text" die neue Liste ausgebe dann hab ich ein Speicher Problem.

Wie kann ich also ohne großen Speicherbedarf rießen Liste, zügig zusammenführen :)

DeddyH 7. Apr 2011 11:06

AW: Große Textdateien verarbeiten
 
Memo.Lines.BeginUpdate und Memo.Lines.EndUpdate benutzt Du bereits?

-187- 7. Apr 2011 11:15

AW: Große Textdateien verarbeiten
 
Hmm ne :) Hört sich Interessant an :)

Werde es gleich testen.

himitsu 7. Apr 2011 11:25

AW: Große Textdateien verarbeiten
 
sl.Text hängt alle Zeilen zu einem String zusammen ... also in der SL liegt jede Zeile als eigenständiger String rum und danach müssen Alle nochmal in einen gemeinsamen String rein > doppelder Speicher und diesmal muß er sogar zusammenhängend im RAM vorliegen.

Delphi-Quellcode:
Memo1.Lines.AddStrings(sl);
(ich weiß jetzt nicht, ob da schon ein BeginUpdate enthalten ist)

-187- 7. Apr 2011 11:28

AW: Große Textdateien verarbeiten
 
Hmm dauert immernoch lange...

Mein System: Quad Core, 2Ghz, 4GB Ram

Hier eine Test Procedure. Vor dem Aufruf wird "Memo1.Lines.BeginUpdate;" und hinterher "Memo1.Lines.EndUpdate;" aufgerufen ..

Delphi-Quellcode:
  for i:=1 to Form1.StringGrid1.RowCount do
  begin
    Path:=Form1.StringGrid1.Cells[1,i];
    if FileExists(Path) then
    begin
      AssignFile(F,Path);
      Reset(F);
      while not eof(F) do
        begin
          Readln(F,tmp);
          Form1.Memo1.Lines.Add(tmp);
        end;
      CloseFile(F);
    end;
  end;

Bbommel 7. Apr 2011 12:24

AW: Große Textdateien verarbeiten
 
Hm, ich weiß, dass es nicht immer so beliebt ist, erst mal die eigentliche Frage selbst infrage zu stellen, aber so richtig zurückhalten kann ich mich gerade nicht - rein aus Neugierde - und bitte daher schon mal vorab um Entschuldigung. :)

Was um Gottes Willen willst du denn eigentlich mit einer 500-1000 MB großen Datei in einem Memo? Das kann sich doch kein Mensch niemalsnicht durchlesen... ;)

Wenn es nur um das Zusammenfügen mehrerer Dateien geht, würde ich doch nicht über ein Memo gehen. Und wenn das Ganze doch unbedingt angezeigt werden soll, wäre es vielleicht auch eine Überlegung, nicht immer alles zu laden und anzuzeigen, sondern auch nur das aus der Datei zu holen, was auch gerade für den Benutzer sichtbar ist. Das ist natürlich einiges mehr an Aufwand zu programmieren (man müsste ja eine Art eigenes Memo erstellen, das genau das macht), sollte aber den Speicher schonen und dann wären den Dateigrößen wahrscheinlich gar keine Grenzen durch dein Programm mehr gesetzt.

Bis denn
Bommel

Klaus01 7. Apr 2011 12:28

AW: Große Textdateien verarbeiten
 
Zitat:

Zitat von -187- (Beitrag 1093596)
Hmm im Grunde möchte ich mit einer Schleife mehrere Dateien in einem Memo aneinander hängen.

Du willst 500MByte Textdateien in ein Memo packen - wer will/muss das denn lesen?
Wenn es nur ums zusammenfügen geht, wäre ein nicht visueller Ansatz sinnvoller.

Mit copy auf command Ebene kann man auch Dateien aneinanderhängen.

Grüße
Klaus

-187- 7. Apr 2011 13:13

AW: Große Textdateien verarbeiten
 
Das soll auch keiner lesen jedoch soll es dargestellt werden. -> Kundenwunsch

Das Zusammenfügen soll / kann in nicht visueller Ebene passieren jedoch will ich nicht alles in einer Variable schreiben (Speicher Auslastung).

DeddyH 7. Apr 2011 13:15

AW: Große Textdateien verarbeiten
 
Du sollst etwas darstellen, was dann niemand liest? :gruebel:

Deep-Sea 7. Apr 2011 13:18

AW: Große Textdateien verarbeiten
 
Zitat:

Zitat von -187- (Beitrag 1093619)
Das soll auch keiner lesen jedoch soll es dargestellt werden. -> Kundenwunsch

Jaja, die Kunden :roll:
Wird jede Zeile auch als eigene Zeile dargestellt? Dann wäre z.B. eine ListBox (oder ähnliches) im virtuellen Modus eine Lösung ...

DeddyH 7. Apr 2011 13:21

AW: Große Textdateien verarbeiten
 
Zitat:

Zitat von Deep-Sea (Beitrag 1093622)
Wird jede Zeile auch als eigene Zeile dargestellt? Dann wäre z.B. eine ListBox (oder ähnliches) im virtuellen Modus eine Lösung ...

Oder gleich der VST.

p80286 7. Apr 2011 14:11

AW: Große Textdateien verarbeiten
 
@DeddyH VST?

Wie wäre es denn mit den Methoden aus der guten alten Dos-Zeit?
Du schleppst eine Kombination aus Dateinamen und "Zeilenzeiger" mit und zeigst nur die 1,2,...n Zeilen an, die auf den Bildschirm passen. Das ist auf jeden Fall speicherschonend, aber etwas aufwendig zu programmieren.

Gruß
K-H

DeddyH 7. Apr 2011 14:31

AW: Große Textdateien verarbeiten
 
Virtual String Tree oder auch Virtual Treeview

-187- 7. Apr 2011 14:37

AW: Große Textdateien verarbeiten
 
Ja tatsächlich Kundenwunsch ... Der Kunde möchte dann durch die zusammengefügte Datei in einer Textbox (Memo) scrollen und ggf. Nacharbeitungen vornehmen.

Jedoch besteht der erste Schritt nur aus dem zusammenfügen der Dateien + Darstellung im Memo.

himitsu 7. Apr 2011 14:44

AW: Große Textdateien verarbeiten
 
Die Datei direkt in einen string laden > natürlich die Ansi-Unicode-Umwandlung nicht vergessen, da die Datei bestimmt mit ANSI gefüllt ist und dein Delphi Unicode nutzt.
(oder in einen AnsiString laden und dann Delphi es umwandeln lassen)

Und dann diesen string direkt an Memo1.Text übergeben.


Dateien zusammenfügen, indem alles Dateien hintereinander in den String geladen werden.


Delphi-Quellcode:
if FileExists(Path) then
begin
  AssignFile(F,Path);
  Reset(F);
  while not eof(F) do
  begin
    Readln(F,tmp);
    Form1.Memo1.Lines.Add(tmp);
  end;
  CloseFile(F);
end;
im Vergleich zu Diesem ... was von dem Folgenden dauert denn wie lange?
Delphi-Quellcode:
if FileExists(Path) then
begin
  AssignFile(F,Path);
  // hier noch den Buffer vergrößen
  Reset(F);
  while not eof(F) do
  begin
    Readln(F,tmp);
    //Form1.Memo1.Lines.Add(tmp);
  end;
  CloseFile(F);
end;
Delphi-Quellcode:
if FileExists(Path) then
begin
  AssignFile(F,Path);
  // hier noch den Buffer vergrößen
  Reset(F);
  tmp := 'hier irgendwas mit der durchschnittlichen Länge einer Zeile reinmachen';
  for i := 1 to Anzahl_der_Zeilen do
  //while not eof(F) do
  //begin
  //  Readln(F,tmp);
    Form1.Memo1.Lines.Add(tmp);
  //end;
  CloseFile(F);
end;

-187- 7. Apr 2011 15:04

AW: Große Textdateien verarbeiten
 
Hm also ich hab jetzt grad schonmal gemessen und bin zu folgendem Ergebnis gekommen:

Code:
file: 20mb, 1372022 Lines
time: 10:34 min
Delphi-Quellcode:
begin
  StartTime:=Time;
  Memo1.Lines.BeginUpdate;
  for i:=1 to Form1.StringGrid1.RowCount do
  begin
    Path:=Form1.StringGrid1.Cells[1,i];
    if FileExists(Path) then
    begin
      AssignFile(F,Path);
      Reset(F);
      while not eof(F) do
        begin
          Readln(F,tmp);
          Form1.Memo1.Lines.Add(tmp);
        end;
      CloseFile(F);
    end;
  end;
  Memo1.Lines.EndUpdate;
  EndTime:=Time;
  ShowMessage('Time: '+TimeToStr(EndTime-StartTime));
end;

Code:
file: 20mb, 1372022 Lines
time: 00:22 min
Delphi-Quellcode:
begin
  StartTime:=Time;
  sl:=TStringList.Create;
  for i:=1 to Form1.StringGrid1.RowCount do
  begin
    Path:=Form1.StringGrid1.Cells[1,i];
    if FileExists(Path) then
    begin
      AssignFile(F,Path);
      Reset(F);
      while not eof(F) do
        begin
          Readln(F,tmp);
          sl.Add(tmp);
        end;
      CloseFile(F);
    end;
  end;
  Memo1.Text:=sl.Text;
  sl.Free;
  EndTime:=Time;
  ShowMessage('Time: '+TimeToStr(EndTime-StartTime));
end;

Deep-Sea 7. Apr 2011 15:09

AW: Große Textdateien verarbeiten
 
Zitat:

Zitat von -187- (Beitrag 1093649)
Der Kunde möchte [...] ggf. Nacharbeitungen vornehmen.

Das klappt dann mit virtuellen Systemen nicht mehr ... oder? *deddyh anschiel*

Wie wäre es also doch in etwa so, wie es p80286 vorgeschlagen hat: Nicht alles auf einmal anzeigen. Diese Forum z.B. zeigt ja auch nicht alle Threads einer Kategorie auf einmal an, sondern stückweise verpackt in übersichtliche Seiten :-D

-187- 7. Apr 2011 15:11

AW: Große Textdateien verarbeiten
 
Ich wollt es erstmal mit einfachen Dingen versuchen :) Vielleicht finden wir ja noch eine akzeptable Lösung :/

alfold 7. Apr 2011 15:12

AW: Große Textdateien verarbeiten
 
Nennt man glaube ich dynamisches lesen und bearbeiten von grossen Textdateien!
(evtl gerade erfunden) :wink:
Der Kunde bekommt davon gar nichts mit!
Er scrollt in den Text so, als währe er komplett im Speicher.
alfold

Deep-Sea 7. Apr 2011 15:13

AW: Große Textdateien verarbeiten
 
@-187-:
1GB auf einmal in 'nen Memo zu laden zählt ganz sicher nicht zu "einfach" :wink:
(Ist ein Memo nicht mal auf 64kB begrenz gewesen?:gruebel:)

-187- 7. Apr 2011 15:14

AW: Große Textdateien verarbeiten
 
Das wäre ziemlich einfach über eine DB (DBGrid) zu lösen ... Wäre eine Überlegung wert.

Edit: Oder TDBMemo :P

Deep-Sea 7. Apr 2011 15:15

AW: Große Textdateien verarbeiten
 
Noch mal 'ne Frage: Wie soll denn die evtl. Bearbeitung vom Kunden aussehen? Bzw. was sind es denn überhaupt für Daten? Man kann hier ja nur rumraten :wink:

alfold 7. Apr 2011 15:15

AW: Große Textdateien verarbeiten
 
Zitat:

Zitat von -187- (Beitrag 1093665)
Das wäre ziemlich einfach über eine DB (DBGrid) zu lösen ... Wäre eine Überlegung wert.

Was die textdatei in eine Datenbank und dann im DBGrid anzeigen? neeee:gruebel:

alfold

-187- 7. Apr 2011 15:18

AW: Große Textdateien verarbeiten
 
Ich könnte doch die Datenbank in einem DBMemo wiedergeben, dann werden doch immer nur die Zeile angezeigt die im sichtbaren Bereich liegen ?

p80286 7. Apr 2011 15:22

AW: Große Textdateien verarbeiten
 
Zitat:

Zitat von -187- (Beitrag 1093649)
Ja tatsächlich Kundenwunsch ... Der Kunde möchte dann durch die zusammengefügte Datei in einer Textbox (Memo) scrollen und ggf. Nacharbeitungen vornehmen.

Jedoch besteht der erste Schritt nur aus dem zusammenfügen der Dateien + Darstellung im Memo.

Das hört sich aber verdammt nach einem aufgebohrten Notepad an.
Abgesehen vom zusammenfügen der Dateien (copy dateia+dateib+dateic Datei_alle), wie soll den diese Nachbearbeitung aussehen?

Gruß
K-H

Edith:
Zitat:

Zitat von -187- (Beitrag 1093671)
Ich könnte doch die Datenbank in einem DBMemo wiedergeben, dann werden doch immer nur die Zeile angezeigt die im sichtbaren Bereich liegen ?

und was ist mit dem Speicherbedarf?

alfold 7. Apr 2011 15:24

AW: Große Textdateien verarbeiten
 
Wenn ich den TH richtig verstehe!
Textdatei evtl >500mb, 1 oder mehr textdateien.
Kunde will nun die textdatei bearbeiten lesen und korrgieren, evtl zusammen fügen und wieder lesen/korregieren. Im Speicher nein geht nicht!
Also dynamisch! (sichtbarer bereich)
Der Kunde bekommt von dieser aktion gar nichts mit!

mein Vorschlag:wink:

alfold

-187- 7. Apr 2011 15:24

AW: Große Textdateien verarbeiten
 
Naja Nachbearbeitung ála suchen,finden,ersetzen,custom filter,löschen etc...

alfold 7. Apr 2011 15:30

AW: Große Textdateien verarbeiten
 
Zitat:

Zitat von -187- (Beitrag 1093675)
Naja Nachbearbeitung ála suchen,finden,ersetzen,custom filter,löschen etc...

und?
Sucht er eine Wort, kann die Textdatei von der platte gescannt werden.
Gefunden, wird die gefundene Stelle angezeigt! Das gleiche mit ersezten usw!

Der Kunde bekommt nicht mal mit das es im Hintergrund abläuft!(auf platte) Das machen andere Programme nicht anders!

Gruss alfold

-187- 7. Apr 2011 15:32

AW: Große Textdateien verarbeiten
 
Wieso und ? Ich hab doch überhaupt kein Einwand gegen deinen Vorschlag gebracht ? ! ;)

alfold 7. Apr 2011 15:34

AW: Große Textdateien verarbeiten
 
Oopps, ich hab das als Frage verstanden, ob das auch damit geht:wink:

alfold

ak-ac 7. Apr 2011 15:59

AW: Große Textdateien verarbeiten
 
Hast Du schon mal drüber nachgedacht, die Sache mit dem Readln fallenzulassen und stattdessen dich anhand der Größe der Festplattencluster zu richten? Das habe ich mal in anderem ZUsamenhang implementiert und wenn du dann die Blöcke nach Zeilen parst (und ggf. noch intelligent diese Cluster im Speicher behälst) kann du dort einiges an Performance reinholen.

Gruss
Alex


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:15 Uhr.
Seite 1 von 2  1 2      

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