11 Stimmen

StringReplace Alternativen zur Verbesserung der Leistung

Ich verwende StringReplace, um > und < durch das Zeichen selbst in einer generierten XML-Datei wie dieser zu ersetzen:

StringReplace(xml.Text,'&gt;','>',[rfReplaceAll]) ;
StringReplace(xml.Text,'&lt;','<',[rfReplaceAll]) ;

Das Problem ist, dass es viel zu lange dauert, jedes Vorkommen von > zu ersetzen.

Haben Sie eine bessere Idee, um es schneller zu machen?

9voto

Bruce McGee Punkte 14836

Wenn Sie Delphi 2009 verwenden, ist dieser Vorgang mit TStringBuilder etwa 3 Mal schneller als mit ReplaceString. Außerdem ist er Unicode-sicher.

Ich habe den Text aus http://www.CodeGear.com mit allen Vorkommnissen von "<" und ">" geändert in "&lt;" y "&gt;" als Ausgangspunkt.

Einschließlich der String-Zuweisungen und der Erstellung/Freigabe von Objekten dauerte dies auf meinem System etwa 25 ms bzw. 75 ms:

function TForm1.TestStringBuilder(const aString: string): string;
var
  sb: TStringBuilder;
begin
  StartTimer;
  sb := TStringBuilder.Create;
  sb.Append(aString);
  sb.Replace('&gt;', '>');
  sb.Replace('&lt;', '<');
  Result := sb.ToString();
  FreeAndNil(sb);
  StopTimer;
end;

function TForm1.TestStringReplace(const aString: string): string;
begin
  StartTimer;
  Result := StringReplace(aString,'&gt;','>',[rfReplaceAll]) ;
  Result := StringReplace(Result,'&lt;','<',[rfReplaceAll]) ;
  StopTimer;
end;

7voto

Versuchen Sie FastStrings.pas von Peter Morris.

6voto

Roddy Punkte 64661

Sie sollten sich unbedingt die Fastcode-Projektseiten ansehen: http://fastcode.sourceforge.net/

Sie haben einen Wettbewerb für ein schnelleres StringReplace durchgeführt (Ansi StringReplace Challenge), und der "Gewinner" war 14 Mal schneller als Delphi RTL.

Einige der Fastcode-Funktionen wurden in neueren Versionen (ab D2007, glaube ich) in Delphi selbst integriert, so dass die Leistungsverbesserung je nach Delphi-Version, die Sie verwenden, stark variieren kann.

Wie bereits erwähnt, sollten Sie wirklich eine Unicode-basierte Lösung in Betracht ziehen, wenn Sie es mit der Verarbeitung von XML ernst meinen.

3voto

Jorge Ferreira Punkte 92489

Das Problem ist, dass Sie die gesamte Zeichenkettengröße zweimal iterieren (einmal zum Ersetzen von > durch > und einmal zum Ersetzen von < durch <).

Sie sollten mit einem for iterieren und einfach immer dann, wenn Sie ein & finden, nach einem gt; oder lt; suchen und die sofortige Ersetzung vornehmen und dann 3 Zeichen überspringen ((g|l)t;). Auf diese Weise kann dies in einer Zeit geschehen, die proportional zur Größe der Zeichenkette ist. xml.Text .


Ein einfaches C#-Beispiel, da ich mich nicht mit Delphi auskenne, sollte aber genügen, um die allgemeine Idee zu verstehen.

String s = "&lt;xml&gt;test&lt;/xml&gt;";
char[] input = s.ToCharArray();
char[] res = new char[s.Length];
int j = 0;
for (int i = 0, count = input.Length; i < count; ++i)
{
    if (input[i] == '&')
    {
        if (i < count - 3)
        {
            if (input[i + 1] == 'l' || input[i + 1] == 'g')
            {
                if (input[i + 2] == 't' && input[i + 3] == ';')
                {
                    res[j++] = input[i + 1] == 'l' ? '<' : '>';
                    i += 3;
                    continue;
                }
            }
        }
    }

    res[j++] = input[i];
}
Console.WriteLine(new string(res, 0, j));

Diese Ausgaben:

<xml>test</xml>

3voto

rkawano Punkte 2293

Wenn Sie es mit mehrzeiligen Textdateien zu tun haben, können Sie eine gewisse Leistung erzielen, indem Sie sie Zeile für Zeile verarbeiten. Dieser Ansatz reduzierte die Zeit bei >1MB Xml-Dateien um ca. 90% auf den Ersatz.

procedure ReplaceMultilineString(xml: TStrings);
var
  i: Integer;
  line: String;
begin
  for i:=0 to xml.Count-1 do
  begin
    line := xml[i];
    line := StringReplace(line, '&gt;', '>', [rfReplaceAll]);
    line := StringReplace(line, '&lt;', '<', [rfReplaceAll]);
    xml[i] := line;
  end;
end;

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X