AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Programm mit TFilestreams zu langsam

Ein Thema von slang · begonnen am 10. Jan 2007 · letzter Beitrag vom 22. Okt 2008
Antwort Antwort
slang

Registriert seit: 23. Feb 2005
12 Beiträge
 
#1

Programm mit TFilestreams zu langsam

  Alt 10. Jan 2007, 12:31
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:
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.
MfG
slang
  Mit Zitat antworten Zitat
Robert Marquardt
(Gast)

n/a Beiträge
 
#2

Re: Programm mit TFilestreams zu langsam

  Alt 10. Jan 2007, 12:43
Wer einen TFileStream byteweise liest ist selber schuld wenn die Performance darniederliegt. Es wird nicht gepuffert.
Besorg dir doch die JCL von http://jcl.sf.net/daily und benutze einen gepufferten Stream. In JclStreams.pas ist dazu TJclBufferedStream enthalten.
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#3

Re: Programm mit TFilestreams zu langsam

  Alt 10. Jan 2007, 12:59
Hallo,

eine Alternative zum selbstgeschriebenen Programm wäre das GNU Text Utility TR (Translate). Auch damit sollten sich die soft breaks eliminieren lassen.

Grüße vom marabu
  Mit Zitat antworten Zitat
slang

Registriert seit: 23. Feb 2005
12 Beiträge
 
#4

Re: Programm mit TFilestreams zu langsam

  Alt 10. Jan 2007, 14:14
Und wie benutze ich diese JclBufferedStreams?
  Mit Zitat antworten Zitat
Robert Marquardt
(Gast)

n/a Beiträge
 
#5

Re: Programm mit TFilestreams zu langsam

  Alt 10. Jan 2007, 14:46
Delphi-Quellcode:
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
TJclBufferedStream versklavt den angegebenen Stream. Das True in Konstruktor setzt OwnsStream womit dann beim Free auch der versklavte Stream freigegeben wird.
Damit braucht man keine separate Variable fuer den Sklaven.
  Mit Zitat antworten Zitat
Benutzerbild von ralfiii
ralfiii

Registriert seit: 30. Mai 2007
489 Beiträge
 
Delphi 2010 Professional
 
#6

Re: Programm mit TFilestreams zu langsam

  Alt 19. Sep 2008, 13:46
????
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;
  Mit Zitat antworten Zitat
Benutzerbild von ralfiii
ralfiii

Registriert seit: 30. Mai 2007
489 Beiträge
 
Delphi 2010 Professional
 
#7

Re: Programm mit TFilestreams zu langsam

  Alt 26. Sep 2008, 15:45
* push *

Kein Kommentar dazu? Von niemanden?
(Ich mein, dass TJclBufferedStream nicht g'scheit funktioniert)
  Mit Zitat antworten Zitat
Benutzerbild von ralfiii
ralfiii

Registriert seit: 30. Mai 2007
489 Beiträge
 
Delphi 2010 Professional
 
#8

Re: Programm mit TFilestreams zu langsam

  Alt 22. Okt 2008, 17:35
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
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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