![]() |
#0 perfomanceschonend aus String entfernen
Hallo,
ich lade mittels folgenden Code eine Text-Datei in mein Programm, dass #0 enthält:
Delphi-Quellcode:
In "S" hab ich dann den String der Datei aber noch mit #0.
//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); Um dieses "Zeichen" jetzt zu entfernen, nutz ich folgenden Code:
Delphi-Quellcode:
Nur ist das jetzt nicht sehr perfomance-schonend.
//#0 durch #32 ersetzen
for i := 1 to length(S) do begin If S[i] = #0 then S[i] := #32; end; 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. |
Re: #0 perfomanceschonend aus String entfernen
Delphi-Quellcode:
?
meinString := Trim(meinString);
|
Re: #0 perfomanceschonend aus String entfernen
Man könnte auch mit StringReplace() arbeiten. Das wird aber im Endeffekt auf das selbe herauskommen
|
Re: #0 perfomanceschonend aus String entfernen
Wenn man mit Zeigern arbeitet, dann sollte das Ratz-Fatz gehen (nur Assembler wäre schneller):
Delphi-Quellcode:
Wenn man "an der RTL vorbei" Strings über Zeiger verändert muss man vorher UniqueString() aufrufen.
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; |
Re: #0 perfomanceschonend aus String entfernen
Warum die ganze streamerei?
Delphi-Quellcode:
Wegen 4MB macht man sich doch nicht mehr ins Hemd *G*
var
sll : tstringlist; sll.loadfromfile('MeineDatei'); sll.Text:=SringReplace(sll.Text,#0,#32); { oder eine andere Ersetzungsroutine } ... Gruß K-H |
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:
oder gleich
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;
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); |
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. |
Re: #0 perfomanceschonend aus String entfernen
Zitat:
Gruß K-h |
Re: #0 perfomanceschonend aus String entfernen
Zitat:
"Professionel" ist wenn der Sourcecode einfach strukturiert und und quasi selbsterklärend ist:
Delphi-Quellcode:
und dann später:
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;
Delphi-Quellcode:
Nix gegen Himitsu, aber die Lösung aus Betrag #6 mit dem Memorystream ist deutlich schwerer zu lesen.
Memo1.Lines.Text := StrReplaceChar(StringStream.DataString, #0, ' ');
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! |
Re: #0 perfomanceschonend aus String entfernen
@shmia
Zitat:
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 09:20 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