Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

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

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

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

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

Блок, закоменнченный в "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;//&#237;&#238;&#226;&#251;&#233; &#240;&#224;&#231;&#236;&#229;&#240;
  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, 14:21   #2
evg_m
Профессионал
 
Регистрация: 20.04.2008
Сообщений: 4,680
Репутация: 2097
По умолчанию

Цитата:
Код:

  //-------------------------------------------------------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, 15:24   #3
Fakov
Форумчанин
 
Регистрация: 13.12.2009
Сообщений: 79
Репутация: 10
По умолчанию

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

Цитата:
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, 18:30   #5
Serge_Bliznykov
МегаМодератор
СуперМодератор
 
Регистрация: 09.01.2008
Сообщений: 24,151
Репутация: 5241
По умолчанию

коллега, простите, а я не понял, а зачем две новые переменные 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 в 18:34.
Serge_Bliznykov вне форума   Ответить с цитированием
Старый 05.07.2018, 09:47   #6
Fakov
Форумчанин
 
Регистрация: 13.12.2009
Сообщений: 79
Репутация: 10
По умолчанию

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

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

Код:

      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 в 10:21.
evg_m на форуме   Ответить с цитированием
Старый 05.07.2018, 10:30   #9
Fakov
Форумчанин
 
Регистрация: 13.12.2009
Сообщений: 79
Репутация: 10
По умолчанию

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

Цитата:
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 вне форума   Ответить с цитированием
Ответ

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Поиск и замена байтов Fakov Общие вопросы Delphi 4 19.06.2018 11: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 22:39
макрос на поиск и замену. Что не так? Viento Microsoft Office Excel 6 11.02.2009 23:36


22:19.


Powered by vBulletin® Version 3.8.8 Beta 2
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru