StringReplace alternatives to improve performance

前端 未结 8 753
温柔的废话
温柔的废话 2021-02-04 12:46

I am using StringReplace to replace > and < by the char itself in a generated XML like this:

StringReplace(xml.Text,\'>\',\'>\',[rfReplaceA         


        
相关标签:
8条回答
  • 2021-02-04 13:31

    If you're using Delphi 2009, this operation is about 3 times faster with TStringBuilder than with ReplaceString. It's Unicode safe, too.

    I used the text from http://www.CodeGear.com with all occurrences of "<" and ">" changed to "&lt;" and "&gt;" as my starting point.

    Including string assignments and creating/freeing objects, these took about 25ms and 75ms respectively on my system:

    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;
    
    0 讨论(0)
  • 2021-02-04 13:34

    it's work like charm so fast trust it

        Function NewStringReplace(const S, OldPattern, NewPattern: string;  Flags: TReplaceFlags): string;
    var
      OldPat,Srch: string; // Srch and Oldp can contain uppercase versions of S,OldPattern
      PatLength,NewPatLength,P,i,PatCount,PrevP: Integer;
      c,d: pchar;
    begin
      PatLength:=Length(OldPattern);
      if PatLength=0 then begin
        Result:=S;
        exit;
      end;
    
      if rfIgnoreCase in Flags then begin
        Srch:=AnsiUpperCase(S);
        OldPat:=AnsiUpperCase(OldPattern);
      end else begin
        Srch:=S;
        OldPat:=OldPattern;
      end;
    
      PatLength:=Length(OldPat);
      if Length(NewPattern)=PatLength then begin
        //Result length will not change
        Result:=S;
        P:=1;
        repeat
          P:=PosEx(OldPat,Srch,P);
          if P>0 then begin
            for i:=1 to PatLength do
              Result[P+i-1]:=NewPattern[i];
            if not (rfReplaceAll in Flags) then exit;
            inc(P,PatLength);
          end;
        until p=0;
      end else begin
        //Different pattern length -> Result length will change
        //To avoid creating a lot of temporary strings, we count how many
        //replacements we're going to make.
        P:=1; PatCount:=0;
        repeat
          P:=PosEx(OldPat,Srch,P);
          if P>0 then begin
            inc(P,PatLength);
            inc(PatCount);
            if not (rfReplaceAll in Flags) then break;
          end;
        until p=0;
        if PatCount=0 then begin
          Result:=S;
          exit;
        end;
        NewPatLength:=Length(NewPattern);
        SetLength(Result,Length(S)+PatCount*(NewPatLength-PatLength));
        P:=1; PrevP:=0;
        c:=pchar(Result); d:=pchar(S);
        repeat
          P:=PosEx(OldPat,Srch,P);
          if P>0 then begin
            for i:=PrevP+1 to P-1 do begin
              c^:=d^;
              inc(c); inc(d);
            end;
            for i:=1 to NewPatLength do begin
              c^:=NewPattern[i];
              inc(c);
            end;
            if not (rfReplaceAll in Flags) then exit;
            inc(P,PatLength);
            inc(d,PatLength);
            PrevP:=P-1;
          end else begin
            for i:=PrevP+1 to Length(S) do begin
              c^:=d^;
              inc(c); inc(d);
            end;
          end;
        until p=0;
      end;
    end;
    
    0 讨论(0)
提交回复
热议问题