AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi im FileStream bestimmte Zeichen ersetzen

im FileStream bestimmte Zeichen ersetzen

Ein Thema von fips0705 · begonnen am 3. Jun 2009 · letzter Beitrag vom 5. Jun 2009
Antwort Antwort
Seite 2 von 2     12
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.122 Beiträge
 
Delphi 12 Athens
 
#11

Re: im FileStream bestimmte Zeichen ersetzen

  Alt 4. Jun 2009, 11:57
nja, jedes Zeichen einzeln an den Temp-String anzuhängen ist nicht grad optimal
(da wird z.B. jedesmal der komplette alte Temp-String, zusammen mit dem neuen Zeichen, in einen neuen Temp-String umkopiert)

du kannst die Daten auch direkt im String ersetzen

Delphi-Quellcode:
function FileToStringErsetze(const FileName: String; zuErsetzendeZeichen, NeueZeichen: AnsiChar): AnsiString;
var fs: TFileStream;
begin
  fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    SetLength(Result, fs.Size);
    if fs.Size > 0 then fs.ReadBuffer(Result[1], Length(Result));
    for i := 1 to Length(Result) do
      if Result[i] = zuErsetzendeZeichen then Result[i] := NeueZeichen;
  finally
    fs.Free;
  end;
end;

s := FileToStringErsetze(opendialog1.filename, #00, '|');


falls dich noch andere Zeichen stören, so könnte man z.B. gleich alle Steuerzeichen (unterhalb des Leertaste) ersetzen ... abgesehn von Zeilenumbruch und Tabulator
Delphi-Quellcode:
function FileToStringErsetze(const FileName: String; NeueZeichen: AnsiChar): AnsiString;
var fs: TFileStream;
begin
  fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    SetLength(Result, fs.Size);
    if fs.Size > 0 then
      fs.ReadBuffer(Result[1], Length(Result));
    for i := 1 to Length(Result) do
      if Result[i] in [#0..#8, #11, #12, #14..#31] then
        Result[i] := NeueZeichen;
  finally
    fs.Free;
  end;
end;

s := FileToStringErsetze(opendialog1.filename, '|');
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PosEx im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Satty67

Registriert seit: 24. Feb 2007
Ort: Baden
1.566 Beiträge
 
Delphi 2007 Professional
 
#12

Re: im FileStream bestimmte Zeichen ersetzen

  Alt 4. Jun 2009, 12:21
Hab es mal gemessen... die Variante von himitsu ist etwa 50x schneller

Falls es überhaupt noch jemand interessiert
Delphi-Quellcode:
procedure MakeZeroFilledFile;
var
  FileStream : TFileStream;
  Buffer : array[0..1023] of Byte;
  i : Integer;
begin
  FileStream := TFileStream.Create('F:\WorkTemp\Leerfile.dat', fmCreate);
  FillChar(Buffer,SizeOf(Buffer),#0);
  for i := 0 to (1024*10) do
    FileStream.Write(Buffer,SizeOf(Buffer));
  FileStream.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  aString : String;
begin
  MakeZeroFilledFile;
  StopUhr.Start;
  aString := FileToStringErsetze2('F:\WorkTemp\Leerfile.dat','X',#0);
  StopUhr.Stop;
  ShowMessage(IntToStr(Length(aString))+' - '+StopUhr.StoppedTimeStr);

  MakeZeroFilledFile;
  StopUhr.Start;
  aString := FileToStringErsetze('F:\WorkTemp\Leerfile.dat','X',0);
  StopUhr.Stop;
  ShowMessage(IntToStr(Length(aString))+' - '+StopUhr.StoppedTimeStr);
end;
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#13

Re: im FileStream bestimmte Zeichen ersetzen

  Alt 4. Jun 2009, 12:26
Hallo zusammen,

falls es sich um das Ersetzen von einzelnen Zeichen dreht, nutze ich immer so etwas:

Delphi-Quellcode:
var
  UT = array [0..255] of byte;

...
  // array initialisieren
  for i:=0 to 255 do
    UT[i]:=i;
  //zu übersetzende Zeichen definieren
  UT[$0A]:=$20;
....

for i:=0 to sizeof(buffer)-1 do
  buffer[i]:=UT[buffer[i]];
Gruß
K-H

[edit] Die Zeit hab ich noch nie gemessen! [/edit]
  Mit Zitat antworten Zitat
fips0705

Registriert seit: 13. Sep 2006
45 Beiträge
 
#14

Re: im FileStream bestimmte Zeichen ersetzen

  Alt 4. Jun 2009, 14:05
Vielen Dank, dann werde ich wohl den Code von himitsu nehmen da er auch profesioneller ist und wesentlich schnellere.
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#15

Re: im FileStream bestimmte Zeichen ersetzen

  Alt 4. Jun 2009, 18:04
Nun, dann sind wir doch wieder bei meinen Funktionen von Betrag #6.
Es ist doch programmiertechnisch besser die Aufgabe wie folgt zu lösen:
Delphi-Quellcode:
var
  daten : string;
begin
  daten := FileToString(dateiname);
  StrReplaceCharsInplace(daten, [#0..#31], '|'); // Steuerzeichen durch Pipezeichen ersetzen
  StringToFile(daten, dateiname);
end;

function StrReplaceCharsInplace(var S: AnsiString; const Chars: TSysCharSet; Replace: AnsiChar): AnsiString;
var
  I: Integer;
begin
  for I := 1 to Length(S) do
    if S[I] in Chars then
      S[I] := Replace;
end;
Die verwendeten Funktionen FileToString, ReplaceCharInplace und StringToFile haben jeweils eine ganz begrenzte Aufgabe.
Man könnte die Funktionen als "atomar" bezeichnen - man kann nichts weglassen ohne dass die gesamte Funktion nutzlos würde.
Diese Funktionen sollten in keiner Bibliothek fehlen; man kann sie immer wieder verwenden!

Die Funktion FileToStringErsetze() ist dagegen ziemlich speziell und wäre in einer Bibliothek eher weniger nützlich.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#16

Re: im FileStream bestimmte Zeichen ersetzen

  Alt 5. Jun 2009, 15:06
Hallo zusammen,

Ich habe aus lauter Langeweile einmal ausprobiert ob StrReplaceCharsInplace oder meine "ArrayLösung" schneller ist. Selbst unter Beachtung von "wer misst misst Mist" bin ich auf folgendes Ergebnis gestoßen:

Bis ca. 5-10 MB Dateigröße hat StrReplaceCharsInplace die Nase vorn, erst ab ca. 50 MB ist die "ArrayLösung" schneller.

Abgesehen davon, daß selten so große oder größere Dateien verarbeitet werden, und die Geschwindigkeit immer noch "gefühlt" gleich ist, irritiert mich, daß der Initialisierungsoverhead sich so stark bemerkbar macht.

Habt Ihr eine Erklährung für mich?

Gruß
K-H
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#17

Re: im FileStream bestimmte Zeichen ersetzen

  Alt 5. Jun 2009, 15:21
Die "Array-Lösung" ist vorallem dann angebracht, wenn man beliebige Umschlüsselungen von einzelnen Zeichen vornehmen möchte.
Falls man nur ein einziges Ersetzungzeichen hat (im deinem Beispiel das '|') dann wird wohl folgende Funktion
die maximale Leistung bringen:
Delphi-Quellcode:
function StrReplaceCharsInplace(var S: AnsiString; const Chars: TSysCharSet; Replace: AnsiChar): AnsiString;
var
  I: Integer;
  p : PChar;
begin
  UniqueString(S);
  p := PChar(S);
  for I := Length(S)-1 downto 0 do
  begin
    if p^ in Chars then
      p^ := Replace;
    Inc(p);
  end;
end;
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#18

Re: im FileStream bestimmte Zeichen ersetzen

  Alt 5. Jun 2009, 15:37
Hallo Andreas,

Daß diese Lösung schnell ist (für mich überraschend, da zu Pascal-Zeiten Sets die Bremse überhaupt waren) kann ich nur bestätigen.

Aber gefühlt kann ich nicht glauben das
If x in IrgendeinerMenge then schneller sein soll als ein simples
for i:=1 to z do Das es so ist habe ich ja gemerkt, aber warum?

Gruß
K-H

P.S.
Bringt der Zugriff über Pointer und mir Rückwärtszählung Soo viel?
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#19

Re: im FileStream bestimmte Zeichen ersetzen

  Alt 5. Jun 2009, 15:53
Zitat von p80286:
If x in IrgendeinerMenge then
In Pseudocode sieht das ungefähr so aus:
if (@IrgendeinerMenge + (x shr 3 ))^ and (1 shl (x and $7)) <> 0 then Man testet praktisch, ob das x.te Bit in der Menge gesetzt ist.
Die Operationen Addition, Links/Rechtsschieben, AND-Verknüpfung sowie Vergleich mit 0 sind alle recht flott.
Zitat von p80286:
Bringt der Zugriff über Pointer und mir Rückwärtszählung Soo viel?
Der Pointerzugriff macht schon Einiges aus; die Rückwärtsschleife dagegen so gut wie nichts,
weil der Compiler sowieso eine Rückwärtsschleife angesetzt hätte, weil die Indexvariable nicht benützt wird.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#20

Re: im FileStream bestimmte Zeichen ersetzen

  Alt 5. Jun 2009, 16:26
Danke!

Gut zu wissen warum!

Gruß
K-H
  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:23 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