![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
|
|
#1
|
|||
|
|||
|
Здравствуйте. Повторюсь в в данном вопросе я ноль. Ибо не интересовался по работе с бинарным данными. Однако по ответам с друогих форумах имею представления что встроенного функционала на подобие функций Pos, Copy и Delete нету для работы с набором байтов.
Короче нужно 3 примера: 1. Замена байтов на такоеже количество. 2. Замена байт если длинна заменяемых данных больше длинны искомых. 3. Замена байт если длинна заменяемых данных меньше чем длина искомых. И да нужно именно заменить удалив лишнии Что до 2 варианта о данные например такие: Код:
PATTERN1: array [0..9] of Byte = ($03, $05, $00, $00, $00, $63, $69, $62, $3D, $31); PATTERN2: array [0..11] of Byte = ($03, $07, $00, $00, $00, $63, $69, $62, $3D, $39, $39, $39); Код:
PATTERN1: array [0..10] of Byte = ($03, $06, $00, $00, $00, $63, $69, $62, $3D, $2D, $31); PATTERN2: array [0..9] of Byte = ($03, $05, $00, $00, $00, $63, $69, $62, $3D, $39); Цитата:
|
|
#2
|
||||
|
||||
|
Я бы работал с классом TFileStream. Считали блок данных размером с искомый паттерн, и посимвольно пробегаем в поиске первого байта паттерна. Если нашли, то запоминаем позицию (начало искомой последовательности) и проверяем следующий бай. Совпал - продолжаем с третьим и т.д. на всю длину паттерна. (если дошли до конца прочитанного блока, то дочитываем недостающую длину и продолжаем сверку). Если же ничего не нашлось, то снова считываем следующую партию байт и повторяем процесс пока не найдем всю последовательность.
А дальше бы уже прибегнул к дополнительному потоку (хоть TFileStream, хоть TMemoryStream). Копируем в дополнительный поток все что до начала искомого паттерна, потом записываем нужный паттерн (PATTERN2) и повторяем все действия до конца файла. Если нужно, то переносите содержимое дополнительного потока в первый и сохраняете. Или же оригинальный файл переименовывем и сохраняем доп.поток в файл с прежним именем. С таким подходом не будет никакой разницы какой, какой паттерн длиннее или короче, хоть вообще "удалять" искомый набор байт. Последний раз редактировалось dr. F.I.N., 09.07.2020 в 19:24. |
|
#3
|
|||
|
|||
|
Цитата:
Нужно учитывать что позиция где эти байты находятся находится неизвестно. И более того находиться они будут всегда в разном месте всеже это не программа. Плюс размер файла большой - 10 - 50 МБ. Число варьируется между этим отрезком. Так что побайтовое чтение будет долгим. Да и мнебы пример. А точнее примеры 3 штуки на 3 варианта. |
|
#4
|
|||
|
|||
|
1. Если работать через TFileStream - то без разницы по байту ты читаешь или по несколько - там все-равно все идет через буфер.
2. Делал в свое время такую штуку (правда не через TFfileStream). Там код довольно сложный получается, если ты не хочешь дублировать файл. 10-50мб это не так и много, так что проще сделать через временный файл. Т.е. читаем исходный файл, меняем данные, если нашли паттерн, и пишем во временный. Потом заменяем файл целиком. |
|
#5
|
|||
|
|||
|
Да лин. Может кто приме мне сделать. Например поменять:
PATTERN1: array [0..9] of Byte = ($03, $05, $00, $00, $00, $63, $69, $62, $3D, $31); на PATTERN2: array [0..11] of Byte = ($03, $07, $00, $00, $00, $63, $69, $62, $3D, $39, $39, $39); и PATTERN1: array [0..10] of Byte = ($03, $06, $00, $00, $00, $63, $69, $62, $3D, $2D, $31); на PATTERN2: array [0..9] of Byte = ($03, $05, $00, $00, $00, $63, $69, $62, $3D, $39); Буду очень благодарен. Ну или если уже есть это то дайте ссылку. |
|
#6
|
||||
|
||||
|
Код:
//Функция поиска шаблона
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;Хотелось бы узнать результаты проверки в боевых условиях. Последний раз редактировалось Kailon, 20.07.2020 в 06:34. |