![]() |
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:
Wie würdet ihr an diese Problemstellung rangehen ?
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; |
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 |
AW: Große Textdateien verarbeiten
Zitat:
Gruß K-H |
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? |
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:) ![]() |
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. |
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. |
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 |
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).
|
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 :) |
AW: Große Textdateien verarbeiten
Memo.Lines.BeginUpdate und Memo.Lines.EndUpdate benutzt Du bereits?
|
AW: Große Textdateien verarbeiten
Hmm ne :) Hört sich Interessant an :)
Werde es gleich testen. |
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:
(ich weiß jetzt nicht, ob da schon ein BeginUpdate enthalten ist)
Memo1.Lines.AddStrings(sl);
|
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; |
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 |
AW: Große Textdateien verarbeiten
Zitat:
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 |
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). |
AW: Große Textdateien verarbeiten
Du sollst etwas darstellen, was dann niemand liest? :gruebel:
|
AW: Große Textdateien verarbeiten
Zitat:
Wird jede Zeile auch als eigene Zeile dargestellt? Dann wäre z.B. eine ListBox (oder ähnliches) im virtuellen Modus eine Lösung ... |
AW: Große Textdateien verarbeiten
Zitat:
|
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 |
AW: Große Textdateien verarbeiten
![]() |
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. |
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:
im Vergleich zu Diesem ... was von dem Folgenden dauert denn wie lange?
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;
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; |
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; |
AW: Große Textdateien verarbeiten
Zitat:
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 |
AW: Große Textdateien verarbeiten
Ich wollt es erstmal mit einfachen Dingen versuchen :) Vielleicht finden wir ja noch eine akzeptable Lösung :/
|
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 |
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:) |
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 |
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:
|
AW: Große Textdateien verarbeiten
Zitat:
alfold |
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 ?
|
AW: Große Textdateien verarbeiten
Zitat:
Abgesehen vom zusammenfügen der Dateien (copy dateia+dateib+dateic Datei_alle), wie soll den diese Nachbearbeitung aussehen? Gruß K-H Edith: Zitat:
|
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 |
AW: Große Textdateien verarbeiten
Naja Nachbearbeitung ála suchen,finden,ersetzen,custom filter,löschen etc...
|
AW: Große Textdateien verarbeiten
Zitat:
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 |
AW: Große Textdateien verarbeiten
Wieso und ? Ich hab doch überhaupt kein Einwand gegen deinen Vorschlag gebracht ? ! ;)
|
AW: Große Textdateien verarbeiten
Oopps, ich hab das als Frage verstanden, ob das auch damit geht:wink:
alfold |
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 08:20 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