Показать сообщение отдельно
  #6  
Старый 19.07.2020, 07:02
Аватар для Kailon
Kailon Kailon вне форума
Активный
 
Регистрация: 06.06.2010
Сообщения: 339
Версия Delphi: 10.4
Репутация: 429
Сообщение

Код:
//Функция поиска шаблона
function PatternSearch(aPattern: TBytes; aFileName: String): LongInt;
var
  F: TMemoryStream;
  Buf: TBytes;
  Len, Step: LongInt;
begin
  F := TMemoryStream.Create;
  F.LoadFromFile(aFileName);
  try
    Len := Length(aPattern);
    SetLength(Buf, Len);
    Step := 0;
    try
      repeat
        F.Seek(Step, soFromBeginning);
        F.ReadBuffer(Buf, Len);
        Inc(Step);
      until CompareMem(Buf, aPattern, Len);
      Result := F.Position;
    except
      Result := -1;
    end;
  finally
    F.Free;
  end;
end;

Код:
//Процедура замены одного шаблона на другой
procedure ReplacePattern(aFileName: String; aOffset: LongInt;
  OldPattern, NewPattern: TBytes);
var
  InF, OutF: TMemoryStream;
  OldLen, NewLen: LongInt;
  FirstFilePart, SecondFilePart: TBytes;
begin
  OldLen := Length(OldPattern);
  NewLen := Length(NewPattern);
  InF := TMemoryStream.Create;
  OutF := TMemoryStream.Create;
  InF.LoadFromFile(aFileName);
  RenameFile(aFileName, aFileName + '.bak');
//  DeleteFile(aFileName);
  try
    if OldLen = NewLen then
    begin
      InF.Seek(aOffset, soFromBeginning);
      InF.WriteBuffer(NewPattern, NewLen);
      InF.SaveToFile(aFileName);
    end
    else
    begin
      SetLength(FirstFilePart, aOffset);
      InF.ReadBuffer(FirstFilePart, aOffset);
      InF.Seek(OldLen, soFromCurrent);
      SetLength(SecondFilePart, InF.Size - Length(FirstFilePart) - OldLen);
      InF.ReadBuffer(SecondFilePart, Length(SecondFilePart));
      OutF.WriteBuffer(FirstFilePart, Length(FirstFilePart));
      OutF.WriteBuffer(NewPattern, Length(NewPattern));
      OutF.WriteBuffer(SecondFilePart, Length(SecondFilePart));
      OutF.SaveToFile(aFileName);
    end;
  finally
    InF.Free;
    OutF.Free;
    SetLength(FirstFilePart, 0);
    SetLength(SecondFilePart, 0);
  end;
end;

Код:
//Пример использования
procedure TForm1.Button1Click(Sender: TObject);
const
  aFileName = 'd:\Test.pdf';
  Buf1: TBytes = [$65, $0A, $2F, $58, $4F, $62, $6A, $65, $63, $74, $2F, $4C, $65, $6E, $67, $74];
  Buf2: TBytes = [$FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF];
var
  Offset: LongInt;
begin
  Offset := PatternSearch(Buf1, aFileName);
  if Offset >= 0 then
    ReplacePattern(aFileName, Offset, Buf1, Buf2);
end;

Хотелось бы узнать результаты проверки в боевых условиях.
__________________
Всегда пишите код так, будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете.
Ответить с цитированием