![]() |
Delphi-Version: 7
Große Textdateien spitten
Hallo DP Team,
ich habe eine Funktion die große Textdateien in 4 Dateien splittet. Nur diese Funktion ist "sehr" langsam, Sie benötigt für eine 1,5 GB große Textdatei 102 Sekunden. Da die Dateien die mein Programm bearbeiten soll ungefähr in der Größenordnung von 3-4 GB liegen, braucht die Funktion dafür ca 4,5 Minuten und dies ist zu lang. Gibt es eine Möglichkeit oder eine Funktion die das wesentlich schneller machen kann? Wichtig zu wissen ist, dass die Datei nur Zeilenweise gesplittet werden kann. Hier der Funktionscode;
Delphi-Quellcode:
VG
For i := 0 to 3 do
begin AssignFile(F[i],ExtractFilePath(ParamStr(0)) + 'Test_' + IntToStr(i) + '.txt'); ReWrite(F[i]); end; i := 0; AssignFile(ff,Epfad.Text); Reset(ff); while not eof(ff) do begin inc(i); ReadLn(ff, TestText); Case i of 1: WriteLn(F[0],TestText); 2: WriteLn(F[1],TestText); 3: WriteLn(F[2],TestText); 4: WriteLn(F[3],TestText); end; If i = 4 Then i := 0; end; CloseFile(F[0]); CloseFile(F[1]); CloseFile(F[2]); CloseFile(F[3]); Vielen Dank und Grüße |
AW: Große Textdateien spitten
Wie lang sind die Zeilen?
Die einfachste Variante würde eine Vergrößerung des Caches bedeuten. Die Uralten Funktionen AssignFile+TEXT nutzen einen Cache von 128 Byte je Datei und das ist natürlich extrems unökonomisch. (vorallem da alleine schon die Sektoren/Cluster des Datenträgers wesentlich größer sind) Siehe OH von Reset/Rewrite. |
AW: Große Textdateien spitten
Sehe ich das richtig: jede Zeile kommt in eine andere Datei und nach 4 Zeilen fängt es wieder von vorne an? In dem Fall kommst du um ein zeilenweises Lesen, wie es aktuell implementiert ist, wohl nicht herum.
Man könnte allenfalls noch was mit Textbuffern machen: ![]() |
AW: Große Textdateien spitten
Zitat:
Es kann aber sein, dass die Zeilen länger werden, da es sich um eine Fehlerdatei einer Datenintegritätsprüfung einer Datenbank handelt. Hier mal eine Beispielzeile: Warnung: 'Fibu Buch.-Blattname' existiert nicht. Buch.-Blattvorlagenname: ALLGEMEIN, Name: LOHN 02/06 Das Feld Buch.-Blattname in der Tabelle Fibu Buch.-Blattzeile hat eine Tabellenrelation auf das Feld Name in der Tabelle Fibu Buch.-Blattname. 'Fibu Buch.-Blattzeile' ist durch die folgenden Felder und Werte bestimmt: Buch.-Blattvorlagenname='ALLGEMEIN',Buch.-Blattname='LOHN 02/06',Zeilennr.='337000' Zitat:
Mein Programm analysiert diese Zeilen und diesen Prozess will ich beschleunigen indem ich die Datei in 4 gleich große Dateien splitte und in 4 Threads gleichzeitig bearbeite. |
AW: Große Textdateien spitten
Vielleucht könnte
![]() ![]() Ich würde eher versuchen Chunks in M;emory einzulesen, und die dann im Memory zu analysieren. Rollo |
AW: Große Textdateien spitten
Um es zu Beschleunigen willst du es also 5 Dateien lesen und 4 Dateien auf die "langsame" Platte schreiben?
Warum nicht die Datei einmal einlesen und dabei die gelesenen Zeilen direkt an die Threads weiterreichen? |
AW: Große Textdateien spitten
Zitat:
Ich speichere ja die Werte zurück und Überprüfe daraufhin auf doppelte Werte. Da müssen ja dann die threads drauf warten bis die Überprüfung von einem thread fertig ist oder? 🤔 |
AW: Große Textdateien spitten
Wie wäre es denn mit Memory Mapped Files von Herrn Jaenike?
Ließt unheimlich schnell ein und die Zeilen stehen auch schnell zur Verfügung. ![]() |
AW: Große Textdateien spitten
Hab' mal ein bisserl rumgespielt, rausgekommen ist dashier:
Delphi-Quellcode:
Hinter der Konstante Buffer_Size steht jeweils, wielange mein Rechner für die Aufteilung einer Datei von 1.250.375.501 Byte benötigt hat.
program Project1;
{$APPTYPE CONSOLE} uses SysUtils, Classes; const // BUFFER_SIZE = 16384; // 1:19 // BUFFER_SIZE = 65536; // 1:07 // BUFFER_SIZE = 65536 * 2; // 1:03 BUFFER_SIZE = 65536 * 4; // 0:53 // BUFFER_SIZE = 65536 * 8; // 2:07 arLow = 0; arHigh = 3; var i : Integer; f : array[arLow..arHigh] of TextFile; ff : TextFile; inf_buf : array[1..BUFFER_SIZE] of Byte; utf_buf : array[1..BUFFER_SIZE] of Byte; sIn : String; sOut : Array[arLow..arHigh] of String; sZeile : String; dtStart : TDateTime; dtEnde : TDateTime; begin dtStart := Now; WriteLn('Start : ' + DateTimeToStr(dtStart)); sIn := ParamStr(1); For i := Low(f) to High(f) do begin sOut[i] := ExtractFilePath(ParamStr(0)) + 'Test_' + IntToStr(i) + '.txt'; AssignFile(F[i],sOut[i]); SetTextBuf(F[i],utf_buf, BUFFER_SIZE); ReWrite(F[i]); end; i := 0; AssignFile(ff,sIn); SetTextBuf(ff,inf_buf,BUFFER_SIZE); Reset(ff); while not eof(ff) do begin ReadLn(ff, sZeile); WriteLn(F[i],sZeile); inc(i); If i > arHigh Then i := arLow; end; dtEnde := Now; WriteLn('Ende : ' + DateTimeToStr(dtEnde)); WriteLn('Zeit : ' + TimeToStr(dtEnde - dtStart)); WriteLn('Buffer: ' + IntToStr(Buffer_Size)); WriteLn('Dateigroessen:'); WriteLn('Eingabe: ',FileSize(ff) * Buffer_Size,' (',sIn,')'); CloseFile(ff); for i := Low(f) to High(f) do begin WriteLn('Ausgabe: ',FileSize(f[i]) * Buffer_Size,' (',sOut[i],')'); CloseFile(F[i]); end; end. Eventuell kannst Du damit ja was anfangen. |
AW: Große Textdateien spitten
Hallo Nahpets,
Ich konnte damit die benötigte Zeit von 102 Sekunden auf 25 Sekunden verringern. Vielen Dank Start : 29.10.2017 20:59:44 Ende : 29.10.2017 21:00:10 Zeit : 00:00:25 Buffer: 262144 Dateigroessen: Eingabe: 1535639552 (TestDaten\dbtest_PINAG.txt) Ausgabe: 383778816 (Test_0.txt) Ausgabe: 383778816 (Test_1.txt) Ausgabe: 383778816 (Test_2.txt) Ausgabe: 383778816 (Test_3.txt) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:21 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