this slowpoke moves

Patch File

Das Patchen einer Datei ist eigentlich nichts anderes als die Datei so zu verändern, sodass sie im Nachhinein weiter funktionstüchtig ist. Es können Strings entfernt oder ersetzt werden.

Um einen String aus einer Datei zu entfernen oder zu ersetzen, muss der String erstmal gesucht werden.
Mit dieser Funktion lassen sich Dateien patchen, doch sie ist sensibel. Bei EXE-Dateien sollte man den Inhalt einigermaßen kennen, damit die EXE danach auch weiter funktioniert.
uses Math

type
TReplaceFlags = set of (rfReplaceAll, rfIgnoreCase);

//

function PatchFile(const AFilename: string; AOldText, ANewText: string;
         Flags: TReplaceFlags): boolean;
const
  cMaxBuffer = 128*1024;
var
  f: TFileStream;
  i: integer;
  Buf: array[0..cMaxBuffer-1] of Char;
  OldStr: string;
  StrBuf: string;
begin
  result := false;
  if Length(AOldText) <> Length(ANewText) then exit;

  ZeroMemory(@Buf, cMaxBuffer);
  if rfIgnoreCase in Flags then
    OldStr := AnsiLowerCase(AOldText)
  else
    OldStr := AOldText;

  f := TFileStream.Create(AFilename, fmOpenReadWrite or fmShareDenyWrite);
  try
    while f.Read(Buf, cMaxBuffer) > Length(AOldText) do
    begin
      StrBuf := Buf;
      f.Seek(-Length(AOldText), soFromCurrent);
      if rfIgnoreCase in Flags then
        StrBuf := AnsiLowerCase(StrBuf);
      repeat
       i := Pos(OldStr, StrBuf);
       if i > 0 then
       begin
         result := true;
         Delete(StrBuf, i, length(AOldText));
         Insert(ANewText, StrBuf, i);
         if not (rfReplaceAll in Flags) then
           break;
       end;
     until i = 0;
     f.Position := Max(f.Position + Length(AOldText) - cMaxBuffer, 0);
     f.Write(Pointer(StrBuf)^, Length(StrBuf));
     if result and not (rfReplaceAll in Flags) then exit;
    end;
  finally
    f.Free;
  end;
end;
Beispiel :
procedure TForm1.Button1Click(Sender: TObject);
begin
   if PatchFile('c:\temp.txt', // Pfad der Datei
                'AltText', // Der String der gesucht werden muss
                'NeuText', // Der String der den alten ersetzten soll (Patchen)
                [rfIgnoreCase, rfReplaceAll]) then
    ShowMessage('Found and Patch done')
  else
    ShowMessage('Not found Patch missmatch.');
end;

Keine Kommentare:

Kommentar veröffentlichen

Beliebte Posts

Translate