我使用StringReplace替换& GT和& LT由焦炭本身在生成的XML是这样的:StringReplace的替代品,以提高性能
StringReplace(xml.Text,'>','>',[rfReplaceAll]) ;
StringReplace(xml.Text,'<','<',[rfReplaceAll]) ;
的事情是它需要的方式tooo长替换的每一次出现& gt。
你有什么更好的主意让它更快吗?
我使用StringReplace替换& GT和& LT由焦炭本身在生成的XML是这样的:StringReplace的替代品,以提高性能
StringReplace(xml.Text,'>','>',[rfReplaceAll]) ;
StringReplace(xml.Text,'<','<',[rfReplaceAll]) ;
的事情是它需要的方式tooo长替换的每一次出现& gt。
你有什么更好的主意让它更快吗?
尝试从彼得莫里斯FastStrings.pas。
的问题是,你迭代整个字符串大小的两倍(一个用于替换& GT;可以通过>和另一个替换& lt;通过<)。
你应该迭代一个for,只要你找到一个&就可以检查一下GT;或lt;并立即替换,然后跳过3个字符((g | l)t;)。通过这种方式,它可以在比例的时间内对字符串xml.Text的大小进行处理。
一个简单的C#示例,因为我不知道德尔福,但应该为你做的一般想法。
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>
问题不是迭代字符串两次,而是让它处理许多替换。对于不同的字符串,调用它两次或更多是没有问题的,如果实现它与RTL中的方式不同,则替换它。 – 2011-09-08 19:22:31
由豪费雷拉写入的C#代码的未测试的转换。
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;
这是保存为Unicode吗? – 2008-09-26 16:56:46
Systools(Turbopower,现在开源)有一个ReplaceStringAllL函数,它可以在字符串中执行所有这些函数。
如果您使用的是Delphi 2009,那么使用TStringBuilder比使用ReplaceString快3倍。它也是Unicode安全的。
我使用的文本从http://www.CodeGear.com与变更为"<"
和">"
作为我的出发点的“<”和“>”所有事件。
包括字符串,分配和创建/释放的对象,这些花费了大约25毫秒和75ms分别在我的系统:
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倍。
几个fastcode函数已经包含在Delphi本身的最新版本中(我认为D2007),所以根据你使用的是哪个Delphi版本,性能改进可能会有很大的不同。
如前所述,如果您认真对待处理XML,您应该真的在寻找基于Unicode的解决方案。
当您处理多行文本文件时,您可以通过逐行处理获得一些性能。在我的测试中,这种方法将大约90%的时间减少到大于1MB xml文件的进程替换。
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, '>', '>', [rfReplaceAll]);
line := StringReplace(line, '<', '<', [rfReplaceAll]);
xml[i] := line;
end;
end;
注:德尔福10西雅图。
你可以得到任何关于原始代码Spul vs. Jorge的代码与FastStrings的反馈吗? – gabr 2008-09-27 06:49:01
StringReplace的问题是当您有多个需要替换的事件时。在这种情况下,你应该编写自己的版本,类似于Gabr发布的版本。实际上这个问题不是调用StringReplace 2次,而是让它处理几十个替换。 – 2011-09-08 19:20:48