Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi #0 perfomanceschonend aus String entfernen (https://www.delphipraxis.net/147797-0-perfomanceschonend-aus-string-entfernen.html)

Helmi 16. Feb 2010 15:52


#0 perfomanceschonend aus String entfernen
 
Hallo,

ich lade mittels folgenden Code eine Text-Datei in mein Programm, dass #0 enthält:
Delphi-Quellcode:
  //FileStream und StringStream erzeugen
  FileStream   := TFileStream.Create(Datei, fmOpenRead);
  StringStream := TStringStream.Create(S);

  try
    //FileStream in StringStream kopieren
    FileStream.Position := 0;
    StringStream.CopyFrom(FileStream, FileStream.Size);

    //String aus StringStream auslesen
    StringStream.Position := 0;
    S := StringStream.ReadString(StringStream.Size);
In "S" hab ich dann den String der Datei aber noch mit #0.
Um dieses "Zeichen" jetzt zu entfernen, nutz ich folgenden Code:
Delphi-Quellcode:
    //#0 durch #32 ersetzen
    for i := 1 to length(S) do
      begin
        If S[i] = #0 then
          S[i] := #32;
      end;
Nur ist das jetzt nicht sehr perfomance-schonend.
Vor allem, weil die einzulesende Datei gute 4 MB hat und dementsprechend Zeichen.

Gibt es dafür eine bessere Lösung?

Noch kurz als Info: Momentan arbeite ich dann mit "S", also dem String, weiter.
Ich möchte aber nun das Ganze in eine StringList laden.

Tyrael Y. 16. Feb 2010 15:57

Re: #0 perfomanceschonend aus String entfernen
 
Delphi-Quellcode:
meinString := Trim(meinString);
?

mkinzler 16. Feb 2010 15:58

Re: #0 perfomanceschonend aus String entfernen
 
Man könnte auch mit StringReplace() arbeiten. Das wird aber im Endeffekt auf das selbe herauskommen

shmia 16. Feb 2010 16:05

Re: #0 perfomanceschonend aus String entfernen
 
Wenn man mit Zeigern arbeitet, dann sollte das Ratz-Fatz gehen (nur Assembler wäre schneller):
Delphi-Quellcode:
var
  p : PChar;
  i : integer;
begin
  UniqueString(S);
  p := PChar(S);
  for i := 1 to length(S) do
  begin
    If p^ = #0 then
      p^ := #32;
    Inc(p);
  end;
Wenn man "an der RTL vorbei" Strings über Zeiger verändert muss man vorher UniqueString() aufrufen.

p80286 16. Feb 2010 16:06

Re: #0 perfomanceschonend aus String entfernen
 
Warum die ganze streamerei?
Delphi-Quellcode:
var
  sll : tstringlist;

sll.loadfromfile('MeineDatei');
sll.Text:=SringReplace(sll.Text,#0,#32); { oder eine andere Ersetzungsroutine }
...
Wegen 4MB macht man sich doch nicht mehr ins Hemd *G*

Gruß
K-H

himitsu 16. Feb 2010 16:26

Re: #0 perfomanceschonend aus String entfernen
 
TStringList hört bei #0 auf mit einlesen, also fehlt dann nach dem Einlesen so Einiges,
Aber den TStringStream hätte man sich wohl Sparen können.

Und wie schon gesagt, 4 MB ist für diese FOR-Schleife doch garnichts. :gruebel:

Aber wenn es unbedingt sein muß
Delphi-Quellcode:
var MS: TMemoryStream;
  S: AnsiString;
  i: Integer;
begin
  MS.LoadFromFile(Datei);
  For i := MS.Size - 1 downto 0 do
    If PAnsiChar(MS.Memory)[i] = #0 Then PAnsiChar(MS.Memory)[i] := ' ';
  SetLength(S, MS.Size);
  MoveMemory(@S[1], MS.Memory, MS.Size);
  StringList.Text := S;
oder gleich
Delphi-Quellcode:
var MS: TMemoryStream;
  i: Integer;
begin
  MS.LoadFromFile(Datei);
  For i := MS.Size - 1 downto 0 do
    If PAnsiChar(MS.Memory)[i] = #0 Then PAnsiChar(MS.Memory)[i] := ' ';
  StringList.LoadFormStream(MS);

Helmi 16. Feb 2010 16:42

Re: #0 perfomanceschonend aus String entfernen
 
Hallo,

danke an alle für eure Antworten!

Mir kam das Char-weise durchsteppen durch den String etwas unprofessional (billig) vor.

Aber Himitsu´s MemoryStream-Lösung gefällt mir sehr gut.

p80286 16. Feb 2010 16:51

Re: #0 perfomanceschonend aus String entfernen
 
Zitat:

Zitat von himitsu
TStringList hört bei #0 auf mit einlesen, also fehlt dann nach dem Einlesen so Einiges,

ist ja gut, nicht schlagen,ich kann mich an diese #0 einfach nicht gewöhnen.
Gruß
K-h

shmia 16. Feb 2010 17:14

Re: #0 perfomanceschonend aus String entfernen
 
Zitat:

Zitat von Helmi
Mir kam das Char-weise durchsteppen durch den String etwas unprofessional (billig) vor.

Das scheint nur so.
"Professionel" ist wenn der Sourcecode einfach strukturiert und und quasi selbsterklärend ist:
Delphi-Quellcode:
function StrReplaceChar(const S: Ansistring; const Source, Replace: AnsiChar): string;
var
  I: Integer;
begin
  Result := S;
  // hier besteht noch Optimierungsmöglichkeit durch Verwendung eines Zeigers
  for I := 1 to Length(S) do
    if Result[I] = Source then
      Result[I] := Replace;
end;
und dann später:
Delphi-Quellcode:
Memo1.Lines.Text := StrReplaceChar(StringStream.DataString, #0, ' ');
Nix gegen Himitsu, aber die Lösung aus Betrag #6 mit dem Memorystream ist deutlich schwerer zu lesen.
Der StringStream ist dem Memorystream vorzuziehen, da es viel sicherer und einfacher ist mit Strings zu arbeiten.
(du hast nur noch nicht mitgekriegt, dass man über das Property DataString direkt auf den Inhalt zugreifen kann)
Die potentiell "lebensgefährliche" Funktion MoveMemory() wird vermieden und das ist sehr wichtig für die Softwarequalität.
MoveMemory() ist wie eine geladene Schrotflinte unterm Bett - sie kann dir jederzeit den ganzen Fuss wegschiesen!

p80286 16. Feb 2010 17:35

Re: #0 perfomanceschonend aus String entfernen
 
@shmia
Zitat:

[/delphi]
// hier besteht noch Optimierungsmöglichkeit durch Verwendung eines Zeigers
for I := 1 to Length(S) do
if Result[I] = Source then
Result[I] := Replace;
[delphi]
warum?
Du hast das #4 ja schon angedeutet, aber das
[pre]
For i:=1 to length(s)
...
inc(p)
[/pre]
scheint mir "doppeltgemoppelt" und daher eigentlich ein Performance Killer.

Wenn' unbedingt ein Pointer sein muß hätte ich auf @s[i] getippt;

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:24 Uhr.
Seite 1 von 2  1 2      

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