varios una regulares reemplazar recortar quitar expresiones especiales caracteres cadena all delphi

delphi - una - String Reemplazar alternativas para mejorar el rendimiento



replace c# varios caracteres (7)

Conversión no probada del código C # escrito por Jorge Ferreira.

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;

Estoy usando StringReplace para reemplazar & gt y & lt por el mismo char en un XML generado como este:

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

La cosa es que toma demasiado tiempo reemplazar cada ocurrencia de & gt.

¿Haces alguna idea mejor para hacerlo más rápido?



Systools (Turbopower, ahora de código abierto) tiene una función ReplaceStringAllL que los hace todos en una cadena.


Definitivamente debe mirar las páginas del proyecto de Fastcode: http://fastcode.sourceforge.net/

Ejecutó un desafío para un StringReplace más rápido (desafío Ansi StringReplace), y el ''ganador'' fue 14 veces más rápido que Delphi RTL.

Varias de las funciones de código rápido se han incluido dentro de Delphi en versiones recientes (creo que en D2007), por lo que la mejora del rendimiento puede variar drásticamente dependiendo de la versión de Delphi que esté utilizando.

Como se mencionó anteriormente, realmente debería considerar una solución basada en Unicode si realmente quiere procesar XML.


El problema es que está iterando el tamaño completo de la cadena dos veces (una para reemplazar & gt; por> y otra para reemplazar & lt; por <).

Debe repetir con un y simplemente comprobar siempre que encuentre un & para un gt; o lt; y hacer el reemplazo inmediato y luego omitir 3 caracteres ((g | l) t;). De esta forma puede hacerlo en un tiempo proporcional al tamaño de la cadena xml.Text .

Un simple ejemplo de C # ya que no conozco Delphi, pero debería hacerlo para que usted tenga una idea general.

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));

Esto produce:

<xml>test</xml>


Si está utilizando Delphi 2009, esta operación es aproximadamente 3 veces más rápida con TStringBuilder que con ReplaceString. También es seguro para Unicode.

Utilicé el texto de http://www.CodeGear.com con todas las ocurrencias de "<" y ">" cambiadas a "&lt;" y "&gt;" como mi punto de partida

Incluyendo asignaciones de cadenas y creando / liberando objetos, estos tardaron unos 25 ms y 75 ms respectivamente en mi sistema:

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;


Cuando se trata de archivos de texto de líneas múltiples, puede obtener algún rendimiento procesándolo línea por línea. En mis pruebas, este enfoque redujo el tiempo en aproximadamente 90% para el proceso reemplaza en> 1MB archivo 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, ''&gt;'', ''>'', [rfReplaceAll]); line := StringReplace(line, ''&lt;'', ''<'', [rfReplaceAll]); xml[i] := line; end; end;

Nota: Delphi 10 Seattle.