StringReplace替代品以提高性能
我正在使用StringReplace在生成的XML中用char本身替换&gt和&lt,如下所示:
StringReplace(xml.Text,'>','>',[rfReplaceAll]) ; StringReplace(xml.Text,'<','<',[rfReplaceAll]) ;
事实是,替换&gt的每次出现都花了很长时间。
我们是否有更好的主意来加快速度?
解决方案
问题是我们要遍历整个字符串大小两次(一个用于将>替换为>,另一个用于将<替换为<)。
我们应该以for进行迭代,并且只要找到&for gt就简单地进行检查。或者lt;并立即替换,然后跳过3个字符((g | l)t;)。这样,它可以在与字符串xml.Text的大小成比例的时间内完成此操作。
一个简单的Cexample,因为我不了解Delphi,但应该为我们提供一个大致的思路。
String s = "<xml>test</xml>"; 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));
输出:
<xml>test</xml>
Jorge Ferreira编写的Ccode的未经测试的转换。
function ReplaceLtGt(const s: string): string; var inPtr, outPtr: integer; begin SetLength(Result, Length(s)); inPtr := 1; outPtr := 1; while inPtr <= Length(s) do begin if (s[inPtr] = '&') and ((inPtr + 3) <= Length(s)) and (s[inPtr+1] in ['l', 'g']) and (s[inPtr+2] = 't') and (s[inPtr+3] = ';') then begin if s[inPtr+1] = 'l' then Result[outPtr] := '<' else Result[outPtr] := '>'; Inc(inPtr, 3); end else begin Result[outPtr] := Result[inPtr]; Inc(inPtr); end; Inc(outPtr); end; SetLength(Result, outPtr - 1); end;
尝试使用Peter Morris的FastStrings.pas。
Systools(Turbopower,现在为开放源代码)具有一个ReplaceStringAllL函数,该函数以字符串形式执行所有操作。
如果我们使用的是Delphi 2009,那么使用TStringBuilder进行此操作的速度大约比使用ReplaceString快3倍。这也是Unicode安全的。
我使用来自http://www.CodeGear.com的文本,将所有出现的" <"和">"都更改为"" <"和">"
作为起点。
包括字符串分配和创建/释放对象,这些分别在我的系统上分别花费了25毫秒和75毫秒:
function TForm1.TestStringBuilder(const aString: string): string; var sb: TStringBuilder; begin StartTimer; sb := TStringBuilder.Create; sb.Append(aString); sb.Replace('>', '>'); sb.Replace('<', '<'); Result := sb.ToString(); FreeAndNil(sb); StopTimer; end; function TForm1.TestStringReplace(const aString: string): string; begin StartTimer; Result := StringReplace(aString,'>','>',[rfReplaceAll]) ; Result := StringReplace(Result,'<','<',[rfReplaceAll]) ; StopTimer; end;
我们绝对应该看一下Fastcode项目页面:http://fastcode.sourceforge.net/
他们面临更快的StringReplace挑战(Ansi StringReplace挑战),而"胜利者"的速度是Delphi RTL的14倍。
在最新版本(我认为是D2007版本)中,Delphi本身已包含几个fastcode函数,因此,性能的改进可能会因所使用的Delphi版本不同而有很大差异。
如前所述,如果我们认真对待XML,那么我们应该真正考虑基于Unicode的解决方案。