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的解决方案。

