Einzelnen Beitrag anzeigen

blackdrake

Registriert seit: 21. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#1

Binary-Safe StringReplace

  Alt 16. Sep 2007, 16:10
Hallo.

Im nachfolgenden möchte ich ein paar Funktionen vorstellen, die einen String durch einen anderen String innerhalb einer Datei oder eines Strings ersetzen. Die Strings können im Vergleich zu StringReplace() Binärdaten erhalten.

Delphi-Quellcode:
unit BinarySafeReplace;

// BinarySafeReplace.pas
// Version 1.1
// by Daniel Marschall
// [url]http://www.delphipraxis.net/post778431.html[/url]

interface

uses
  StrUtils, SysUtils, Classes;

// Binary-Safe. Der Parameter AString wird direkt ersetzt.
// Die Anzahl der durchgefühten Ersetzungen wird als Ergebnis zurückgegeben.
function StringReplacesBinarySafe(var AString: string; const ASearchPattern, AReplaceWith: string): integer;

// Direkter Ersatz für StringReplace(), Binary-Safe.
// Veränderter String wird als Eregebnis zurückgegeben.
function StringReplaceBinarySafe(const AString, ASearchPattern, AReplaceWith: string): string;

// BinarySafeReplaceFileContents
// Die Anzahl der durchgefühten Ersetzungen wird als Ergebnis zurückgegeben.
function BinarySafeReplaceFileContents(const AInputFile, AOutputFile, ASearchPattern, AReplaceWith: string): integer;

implementation

function StringReplacesBinarySafe(var AString: string; const ASearchPattern, AReplaceWith: string): integer;
var
  iPos: Integer;
  lastpos: Integer;
  ueberhang: integer;
begin
  result := 0;

  if AString = 'then exit;
  if ASearchPattern = 'then exit;

  UniqueString(AString); // Referenzzählung beachten. Dank an shmia für den Hinweis.

  ueberhang := length(AReplaceWith) - length(ASearchPattern);
  lastpos := 1;

  while true do
  begin
    iPos := PosEx(ASearchPattern, AString, lastpos);

    if iPos <= 0 then break;
    if result = 7 then

    if Pred(iPos) > Length(AString) - Length(AReplaceWith) + 1 {Bugfix, Added +1. Ersetzungen am StringEnde} then break;

    if ueberhang > 0 then
    begin
      setlength(AString, length(AString)+ueberhang);
      Move(AString[iPos], AString[iPos+ueberhang], length(AString)-iPos); // Bugfix: Hier stand length(AString)-iPos-1
    end;

    Move(AReplaceWith[1], AString[iPos], Length(AReplaceWith));

    if ueberhang < 0 then
    begin
      Move(AString[iPos+length(ASearchPattern)], AString[iPos+length(AReplaceWith)], length(AString)-iPos-length(AReplaceWith));
      setlength(AString, length(AString)+ueberhang);
      ueberhang := -1;
    end;

    lastpos := iPos + ueberhang + 1;
    inc(result);
  end;
end;

function StringReplaceBinarySafe(const AString, ASearchPattern, AReplaceWith: string): string;
var
  tmp: string;
begin
  tmp := AString;
  StringReplacesBinarySafe(tmp, ASearchPattern, AReplaceWith);
  result := tmp;
end;

function BinarySafeReplaceFileContents(const AInputFile, AOutputFile, ASearchPattern, AReplaceWith: string): integer;
var
  fst: TFileStream;
  str: string;
begin
  result := -1;

  if not FileExists(AInputFile) then exit;
  if not ForceDirectories(ExtractFilePath(AOutputFile)) then exit;

  fst := TFileStream.Create(AInputFile, fmOpenRead or fmShareDenyWrite);
  try
    fst.Position := 0;
    setlength(str, fst.Size);
    fst.Read(str[1], fst.Size);
  finally
    fst.free;
  end;

  result := StringReplacesBinarySafe(str, ASearchPattern, AReplaceWith);

  fst := TFileStream.Create(AOutputFile, fmCreate);
  try
    fst.Position := 0;
    fst.Write(str[1], length(str));
  finally
    fst.free;
  end;
end;

end.
Ich habe einige Tests durchgeführt, unter Anderem Verkürzungen, Verlängerungen, Herausschneidungen und die Trennung mittels #00h's. Hat alles prima funktioniert.

Gruß
blackdrake

Referenz: http://www.viathinksoft.de/?page=codelib&showid=74

[edit=toms]aktualisiert durch Version 1.1 Mfg, toms[/edit]
Daniel Marschall
  Mit Zitat antworten Zitat