Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 04.07.2018, 12:30   #1
Fakov
Пользователь
 
Регистрация: 13.12.2009
Сообщений: 85
По умолчанию Поправить поиск и замену байтов

Привет всем. Может кто подсказать, как нужно поправить код, чтобы он поочередно нашел сначала одну группу байт в файле, заменил её, а потом нашел и заменил другую группу байт в том же файле???

Блок, закоменнченный в "111.." выполняется, а вот второй круг с поиском блока объявленного в s3 и с заменой на s4 - не происходит.

(желательно максимально для нубов)

Код:
procedure TForm1.Button1Click(Sender: TObject);
var
  F   : TFileStream;
  str : AnsiString;
  pstr, newstr : PAnsiChar;
  s1, s2, s3, s4 : AnsiString;
  i, lastpos, cnt : Integer;
  poss : array of integer;
  newlen : Integer;
  p1, p2, pp : Integer;
begin

s1 := #$00#$42#$54#$4E; 
s2 := #$0D#$42#$54#$4E; 


s3 := #$00#$44#$49#$53; 
s4 := #$0D#$44#$49#$53;
  //s1 := 'BTN'; 
  //s2 := 'FTN'; 
//  s1 := '6789';  
//  s2 := '67'; 
  
   try
    F := TFileStream.Create(OpenDialog1.FileName, fmOpenReadWrite);
    try
      SetLength(str, F.Size);
      SetLength(poss, F.Size);
      F.Read(str[1], F.Size);
    finally
      F.Free;
    end;
  except end;
 
  lastpos := 1; cnt := 0;
  repeat
    i := PosEx(s1, str, lastpos);
    if (i <> 0)
    then
      Begin
        poss[cnt] := i;
        lastpos   := i + 1;
        inc(cnt);
      end;
  until i = 0;
 
  newlen := Length(str) + (Length(s2) - Length(s1)) * cnt;//íîâûé ðàçìåð
  newstr := stralloc(newlen);
  pstr   := PAnsiChar(str);
 
  //-------------------------------------------------------111111111
  p1 := 0; p2 := 0; pp := 1;
  for i := 0 to cnt - 1 do
  begin
    Move(pstr[p1], newstr[p2], poss[i] - pp);
    p2 := p2 + poss[i] - pp;
    pp := poss[i] + Length(s1);
    Move(PAnsiChar(s2)[0], newstr[p2], Length(s2));
    inc(p2, Length(s2));
    p1 := poss[i] + Length(s1) - 1;
  end;
  //-------------------------------------------------------111111111
  //-------------------------------------------------------222222222
  p1 := 0; p2 := 0; pp := 1;
  Move(pstr[p1], newstr[p2], Length(str) - pp + 1);
  for i := 0 to cnt - 1 do
  begin
    Move(pstr[p1], newstr[p2], poss[i] - pp);
    p2 := p2 + poss[i] - pp;
    pp := poss[i] + Length(s3);
    Move(PAnsiChar(s4)[0], newstr[p2], Length(s4));
    inc(p2, Length(s4));
    p1 := poss[i] + Length(s3) - 1;
  end;
  //-------------------------------------------------------222222222
 
  try
    F := TFileStream.Create(OpenDialog1.FileName, fmCreate or fmOpenWrite);
    try
      F.write(newstr[0], newlen);
    finally
      F.Free;
    end;
  except end;
  StrDispose(newstr);

end;
Спасибо.
Fakov вне форума Ответить с цитированием
Старый 04.07.2018, 13:21   #2
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,515
По умолчанию

Цитата:
Код:
  //-------------------------------------------------------222222222
  p1 := 0; p2 := 0; pp := 1;
  Move(pstr[p1], newstr[p2], Length(str) - pp + 1);
  for i := 0 to cnt - 1 do
  begin
    Move(pstr[p1], newstr[p2], poss[i] - pp);
    p2 := p2 + poss[i] - pp;
    pp := poss[i] + Length(s3);
    Move(PAnsiChar(s4)[0], newstr[p2], Length(s4));
    inc(p2, Length(s4));
    p1 := poss[i] + Length(s3) - 1;
  end;
  //-------------------------------------------------------222222222
poss[i] это список найденных ПЕРВЫХ(s1) строк. причем в старой строке.
НАДО аналогично заполнить(найти) ДРУГУЮ(s3) строку в новой.
и после этого формировать еще одну новую(третью) да еще и из правильной(той где искали!)

ECЛИ ... нужно быстро и качественно используй StringReplace
Код:
newstr:=StringReplace(str, s2, s1, [rfreplaceall]);
superstr:=StringReplace(newstr, s4, s3, [rfreplaceall]);
и ВСЕ!!!
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума Ответить с цитированием
Старый 04.07.2018, 14:24   #3
Fakov
Пользователь
 
Регистрация: 13.12.2009
Сообщений: 85
По умолчанию

Знать бы и понимать бы еще как это сделать...
Есть возможность за оч скромное вознаграждение решить этот квест?
Fakov вне форума Ответить с цитированием
Старый 04.07.2018, 17:24   #4
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,515
По умолчанию

Цитата:
ECЛИ ... нужно быстро и качественно используй StringReplace
Код:
rocedure TForm1.Button1Click(Sender: TObject);
var
  F   : TFileStream;
  str : AnsiString;
  newstr, superstr: AnsiString;
  s1, s2, s3, s4 : AnsiString;
begin

s1 := #$00#$42#$54#$4E; 
s2 := #$0D#$42#$54#$4E; 


s3 := #$00#$44#$49#$53; 
s4 := #$0D#$44#$49#$53;
  //s1 := 'BTN'; 
  //s2 := 'FTN'; 
//  s1 := '6789';  
//  s2 := '67'; 
  
    F := TFileStream.Create(OpenDialog1.FileName, fmOpenReadWrite);
    try
      SetLength(str, F.Size);
      F.Read(str[1], F.Size);
    finally
      F.Free;
    end;

  newstr:=StringReplace(str, s2, s1, [frreplacelall]);
  superstr:=StringReplace(newstr, s4, s3, [rfreplaceall]); 
 
    F := TFileStream.Create(OpenDialog1.FileName, fmCreate or fmOpenWrite);
    try
      F.write(superstr[1], length(superstr));
    finally
      F.Free;
    end;

end;
писал естественно на коленке(не проверял).
просто выкинул из кода ВСЮ "поиск и замену" и добавил ДВЕ строчки.
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума Ответить с цитированием
Старый 04.07.2018, 17:30   #5
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,238
По умолчанию

коллега, простите, а я не понял, а зачем две новые переменные newstr и superstr ?

Код:
var
  F   : TFileStream;
  mystr : AnsiString;
....

    F := TFileStream.Create(OpenDialog1.FileName, fmOpenReadWrite);
    try
      SetLength(mystr, F.Size);
      F.Read(mystr[1], F.Size);
    finally
      F.Free;
    end;

  mystr:=StringReplace(mystr, s1, s2, [rfReplaceAll]);
  mystr:=StringReplace(mystr, s3, s4, [rfReplaceAll]); 
 
    F := TFileStream.Create(OpenDialog1.FileName, fmCreate or fmOpenWrite);
    try
      F.write(mystr[1], length(mystr));
    finally
      F.Free;
    end;
исправил порядок замены найти s1 и заменить на s2, потом найти s3 и заменить на s4

Последний раз редактировалось Serge_Bliznykov; 04.07.2018 в 17:34.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 05.07.2018, 08:47   #6
Fakov
Пользователь
 
Регистрация: 13.12.2009
Сообщений: 85
По умолчанию

хм. спасибо всем.
Но код хоть и работает - замену не осуществляет(
То есть файл открывает, но блок байтов не меняется - в первом байте блока не происходит замены с 00 на 0D((
Fakov вне форума Ответить с цитированием
Старый 05.07.2018, 08:58   #7
Fakov
Пользователь
 
Регистрация: 13.12.2009
Сообщений: 85
По умолчанию

попытался вывести из первого примера в label значение переменной superstr (или mystr - без разницы) - оказалось, она пустая(
Fakov вне форума Ответить с цитированием
Старый 05.07.2018, 09:17   #8
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,515
По умолчанию

Код:
      F.Read( @mystr[1], length(mystr)F.Size);//конечно в данном случае(из-за наличияSetLength(mystr, ...) можно и оставить F.Size
Код:
      F.write( @mystr[1], length(mystr));
http://www.programmersforum.ru/showthread.php?t=310349 посты 8(вопрос),10(ответ)
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 05.07.2018 в 09:21.
evg_m вне форума Ответить с цитированием
Старый 05.07.2018, 09:30   #9
Fakov
Пользователь
 
Регистрация: 13.12.2009
Сообщений: 85
По умолчанию

погоды это не изменило - добавление length(mystr) в F.Read не дало результата.
Но хуже другое - как только я добавляю к переменной mystr[1] - знак @ - компилятор начинает ругаться что константный объект не может быть передан как Var-параметр.
Fakov вне форума Ответить с цитированием
Старый 05.07.2018, 10:30   #10
Fakov
Пользователь
 
Регистрация: 13.12.2009
Сообщений: 85
По умолчанию

Цитата:
http://www.programmersforum.ru/showthread.php?t=310349 посты 8(вопрос),10(ответ)
Прочитал, увы по своей малограмотности понял только в общих чертах, что вывести массив байтов в строку не просто изза его структуры.
Однако это не дало пищи для размышления, относительно решения проблемы - код из вашего поста http://www.programmersforum.ru/showp...99&postcount=4 (как впрочем и из следующего поста вашего коллеги) отказывается заменять необходимую группу байт.

Для точности: смысл замены в обновлении первого символа группы байтов - в каждой из пары строк (s1 и s2, s3 и s4) скрыты одни и теже строковые значения (к примеру в паре s1/s2 это значение BTN). Но у каждой этой строки есть 1 байт в начале - $00 - и вот цель заменить именного его, сохранив строку в трех последующих байтах неизменной.
Fakov вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Поиск и замена байтов Fakov Общие вопросы Delphi 4 19.06.2018 10:04
SOS!!! Макрос Excel на поиск и замену слов в таблице. ukk-kz Microsoft Office Excel 2 27.05.2014 10:54
Excel, Как осуществить поиск и замену сразу нескольких фрагментов текста? Танита Помощь студентам 0 24.05.2012 00:18
Поправить прогу... Поиск. twister_answer Помощь студентам 0 06.12.2010 21:39
макрос на поиск и замену. Что не так? Viento Microsoft Office Excel 6 11.02.2009 22:36