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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 02.04.2014, 00:51   #1
XE5
Заблокирован
 
Регистрация: 02.03.2014
Сообщений: 439
По умолчанию Работа с файловыи потоком, поиск порченого байта

Привет всем. Пишу программку по редактированию определённого типа ресурсных файлов. Данный тип содержит изображения, записанные в единый файл последовательно. Моя задача, найти позиции начала, и конца картинки, и заменить имеющуюся картинку своей. Не знаю, можно ли вырезать середину из потока, я поступил следующим образом. Инициализировал новый поток, записал в него данные из исходного потока до начала заменяемого файла, далее записал сам файл, и в конец записал кусок исходного потока после заменяемого файла. Вот основной код подмены файла.

Код:
procedure TForm1.SetFile(Node: TTreeNode; FileName: string);
var
  EndStream: TMemoryStream;
  BufStream: TFileStream;
  num, PosStart: Int64;
begin
  num:= Node.Index;
  PosStart := AResources[Node.Index].StartPosition;

  EndStream := TMemoryStream.Create;
  AMemoryStream.Position := 0;
  EndStream.CopyFrom(AMemoryStream, PosStart);

  BufStream := TFileStream.Create(FileName, fmOpenRead);
  EndStream.CopyFrom(BufStream, BufStream.Size);

  AMemoryStream.Position := AResources[num].EndPosition;
  EndStream.CopyFrom(AMemoryStream, AMemoryStream.Size - AResources[num].EndPosition);
  EndStream.SaveToFile('c:/res');

  Node.SelectedIndex := 1;
  Node.ImageIndex := 1;
end;
Итог. Код работает, но неверно записывается один байт (или два?) состыковывающий начальный блок исходного потока, и вставляемый файл (конец файла, как не странно нормально состыковался с конечным блоком исходного потока). Причём общая длина конечного файла именно такая, какая и должна быть. Собственно вопрос. Почему произошёл сбой в этом байте? По идее напутал с позициями, но не могу отыскать место ошибки. И второй вопрос, есть ли методика замены байтов непосредственно в исходном потоке зная начальную и конечную позиции заменяемого файла? На картинке сравнение правильно переписанного файла, и файла переписанного программой.


Последний раз редактировалось XE5; 02.04.2014 в 02:28.
XE5 вне форума Ответить с цитированием
Старый 02.04.2014, 09:01   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Не видно по этому коду в чем проблема и есть ли она вообще. Код должен вполне корректно заменить участок длиной EndPosition-StartPosition на данные длиной BufStream.Size начиная с позиции StartPosition. Если EndPosition-StartPosition=BufStream.Size, то можно вполне обойтись копированием целиком AMemoryStream в EndStream и одним CopyFrom для замены нужного участка
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию

Последний раз редактировалось Аватар; 02.04.2014 в 09:04.
Аватар вне форума Ответить с цитированием
Старый 02.04.2014, 22:30   #3
XE5
Заблокирован
 
Регистрация: 02.03.2014
Сообщений: 439
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
Если EndPosition-StartPosition=BufStream.Size
Равенство неверно. Этот промежуток занят ресурсом, который мне нужно заменить. Новый ресурс естественно не обязан совпадать размерами с заменяемым ресурсом. Плохо что нет ни каких мыслей о причинах ошибки. Лично я просидел над ней часов шесть, так и не смог её найти. Такое ощущение, что этот байт какой-то флаг. Куда копать, не понимаю. Привожу код процедуры, которая ищет позиции PNG картинок в ресурсе. Может код наведёт на какие-то мысли.

Код:
procedure TForm1.ParseFile;
var
  p: pAnsiChar;
  i64, StartPosition, EndPosition: int64;
begin
  GetMem(p, 3);
  StartPosition := - 1;
  Endposition := - 1;
  i64 := 0;
  while AMemoryStream.Position < AMemoryStream.Size do
    begin
      AMemoryStream.Position := i64;
      AMemoryStream.Read(p^, 3);
      if p = 'PNG' then
        StartPosition := i64 - 1;
      if p = 'END' then
        begin
          EndPosition := i64 + 7;
          if StartPosition > - 1 then
            AddToArray(StartPosition, EndPosition); // дабавление в массив позиций стартовой и конечной позиции PNG
            StartPosition := - 1;
            EndPosition := -1;
        end;
      inc(i64);
    end; 
end;

Последний раз редактировалось XE5; 02.04.2014 в 22:34.
XE5 вне форума Ответить с цитированием
Старый 02.04.2014, 23:38   #4
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

1. Вопрос - зачем стартовая позиция на 1 уменьшается и финишная на 7 увеличивается?
2. Текст 'PNG' и 'END' можно искать с помощью PosEx в StringStream.DataString. В StringStream скопировать тем же CopyFrom из AMemoryStream. Возможно быстрей, не проверял. Но прозрачней точно
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 03.04.2014, 01:44   #5
XE5
Заблокирован
 
Регистрация: 02.03.2014
Сообщений: 439
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
1. Вопрос - зачем стартовая позиция на 1 уменьшается и финишная на 7 увеличивается?
Любой PNG файл в хексе откройте, увидите этот стартовый байт перед PNG. По финишу 3 байта слова END плюс опять же какие-то сервисные байты, которые есть в любом PNG, сдвинув любую из позиций влево/вправо я получаю полную рассинхронизацию байтов.

Цитата:
Сообщение от Аватар Посмотреть сообщение
2. Текст 'PNG' и 'END' можно искать с помощью PosEx в StringStream.DataString. В StringStream скопировать тем же CopyFrom из AMemoryStream. Возможно быстрей, не проверял.
Попробую, но проблему это не решит. По позициям всё чётко. Меняется какой-то байт именно в точке слейки (меняется, а не пропадает! Size на выходе тот что нужен), и не понимаю, по какой причине. Сравнивал с исходными файлами аналогичной программы, всё то же самое. Только там файл вначале полностью разбирался на фрагменты, а потом заново собирался этой же методикой, а я пытаюсь внести изменение без полной пересборки.
XE5 вне форума Ответить с цитированием
Старый 03.04.2014, 04:23   #6
XE5
Заблокирован
 
Регистрация: 02.03.2014
Сообщений: 439
По умолчанию

Всё, нашёл ошибку. Точнее даже не ошибку, а недочёт. Эти два байта это контрольная сумма PNG. Поэтому только в одной точке файла и было несовпадение. Вопрос решён, тема закрыта.
XE5 вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
шифрование байта Oleg1988 Общие вопросы C/C++ 7 31.08.2012 19:41
Работа с потоком Yur@ Общие вопросы Delphi 3 02.06.2011 12:46
Работа с ListView и потоком данных piksel111 Общие вопросы Delphi 4 18.04.2011 01:48
Чтение 0 байта TorrMoZZZZ Помощь студентам 0 26.09.2010 21:44
Поиск первого байта ресурса. Obsever0 Общие вопросы Delphi 2 04.06.2010 13:58