![]() |
Programm mit TFilestreams zu langsam
Hallo!
Ich habe eine kleine Konsolenanwendung geschrieben, welche eine große Datei durchsuchen und bestimmte Zeichenfolgen ersetzen soll. Erstmal soll die ASCII-Folge 139210 durch ASCII 32 ersetzt werden. Danach sollen alle übriggebliebenen ASCII 13 durch ASCII 32 ersetzt werden. Danach sollen alle übriggebliebenen ASCII 10 durch ASCII 1310 ersetzt werden. Das Programm braucht leider für eine 16MB Datei schon ca. 5 Minuten. Es soll aber für Dateien mit über 500MB (eventuell auch über 1GB) eingesetzt werden. Kann mir jemand ein paar Tipps geben, wo ich was verbessern kann bzw. wo mein Programm ausgebremst wird? Hier der komplette Quelltext:
Delphi-Quellcode:
MfG
program ersetze;
{$APPTYPE CONSOLE} uses SysUtils,Classes; var stream1: TFIleStream; stream2: TFileStream; Buf,Buf2,Buf3 : Byte; chSpace,chCR,chLF: char; a,b,c:integer; begin a:=0; b:=0; c:=0; chSpace := #32; chCR := #13; chLF := #10; stream1 := TFileStream.Create('c:\test.unl', fmOpenRead); stream2 := TFileStream.Create('c:\test2.unl', fmCreate); try // Byteweise in Stream1 bis zum Dateiende lesen while stream1.Position < stream1.size do begin stream1.Read(Buf,sizeof(Buf)); if Buf = 13 then // ASCII 13 gefunden -> nächstes Byte muss überprüft werden begin stream1.Read(Buf2,sizeof(Buf2)); if Buf2 = 92 then // ASCII 1392 gefunden -> nächstes Byte muss überprüft werden begin stream1.Read(Buf3,sizeof(Buf3)); if Buf3 = 10 then // ASCII 139210 gefunden begin // Statt ASCII 139210 wird ASCII 32 (Space) in die neue Datei geschrieben stream2.Write(chSpace,sizeof(chSpace)); a := a + 1; end else // kein ASCII 10 an dritter Stelle -> ASCII 32 (Space) in neue Datei schreiben und 2 Bytes zurückspringen begin stream2.Write(chSpace,SizeOf(chSpace)); stream1.Seek(-2,soFromCurrent); b := b + 1; end; end else // kein ASCII 92 an zweiter Stelle -> ASCII 32 (Space) in neue Datei schreiben und 1 Byte zurückspringen begin stream2.Write(chSpace,SizeOf(chSpace)); stream1.Seek(-1,soFromCurrent); b := b + 1; end; end else if Buf = 10 then // Kein ASCII 13 gefunden -> Prüfen ob ASCII 10 gefunden wurde begin // ASCII 10 gefunden -> ASCII 1310 in neue Datei schreiben stream2.Write(chCR,SizeOf(chCR)); stream2.Write(chLF,SizeOf(chLF)); c:=c+1; end else begin // Kein ASCII 10 gefunden -> Buf in Datei schreiben stream2.Write(Buf,SizeOf(Buf)); end; end; finally stream1.Free; stream2.Free; end; writeln('gefundene 0D5C0A: ' + IntToStr(a)); writeln('gefundene 0D: ' + IntToStr(b)); writeln('gefundene 0A: ' + IntToStr(c)); Readln; end. slang |
Re: Programm mit TFilestreams zu langsam
Wer einen TFileStream byteweise liest ist selber schuld wenn die Performance darniederliegt. Es wird nicht gepuffert.
Besorg dir doch die JCL von ![]() |
Re: Programm mit TFilestreams zu langsam
Hallo,
eine Alternative zum selbstgeschriebenen Programm wäre das ![]() Grüße vom marabu |
Re: Programm mit TFilestreams zu langsam
Und wie benutze ich diese JclBufferedStreams?
|
Re: Programm mit TFilestreams zu langsam
Delphi-Quellcode:
TJclBufferedStream versklavt den angegebenen Stream. Das True in Konstruktor setzt OwnsStream womit dann beim Free auch der versklavte Stream freigegeben wird.
var
stream1, stream2: TJclBufferedStream; begin stream1 := TJclBufferedStream.Create(TFileStream.Create('c:\test.unl', fmOpenRead), True); stream2 := TJclBufferedStream.Create(FileStream.Create('c:\test2.unl', fmCreate), True); ... der Rest bleibt gleich Damit braucht man keine separate Variable fuer den Sklaven. |
Re: Programm mit TFilestreams zu langsam
????
Seh ich da was nicht? Ich hab mal schnell den gepufferten Stream getestet und die Performance ist noch deutlich schlechter. "normal" = 1671 "buffered" = 4187
Delphi-Quellcode:
uses JclStreams;
procedure TForm1.Button1Click(Sender: TObject); var counter : integer; StartTime : LongWord; {DEFINE UseBufferendStream} {$IFNDEF UseBufferendStream} fs : TFileStream; {$ELSE} fs : TJclBufferedStream; {$ENDIF} by : byte; const CIterations = 1000000; begin StartTime:=GetTickCount; by:=$0f; {$IFNDEF UseBufferendStream} fs := TFileStream.Create( 'C:\test.txt', fmCreate or fmShareDenyWrite ); {$ELSE} fs := TJclBufferedStream.Create(TFileStream.Create( 'C:\test.txt', fmCreate or fmShareDenyWrite ), True); {$ENDIF} try for counter:=0 to CIterations-1 do fs.write(by, sizeof(by)); finally fs.Free; end; Caption:=IntToStr(GetTickCount - StartTime); end; |
Re: Programm mit TFilestreams zu langsam
* push *
Kein Kommentar dazu? Von niemanden? (Ich mein, dass TJclBufferedStream nicht g'scheit funktioniert) |
Re: Programm mit TFilestreams zu langsam
Sollte es jemanden interessieren:
Das Schreiben hab ich mir noch nicht angesehen, aber beim Lesen gibt's auch eine Besonderheit die mir aufgefallen ist: Die Abfrage von TJclBufferedStream.Size ist tödlich für die Performance! Bei jeder Abfrage springt er zum Ende des Streams was den Cache eliminiert. Also: Wenn die Filegrösse öfter gebracht wird (z.B. um den Fortschritt anzuzeigen: Am Anfang in einer Variable zwischenspeichern! Ralf |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:13 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