Распаковка bzip2 в памяти.

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Распаковка bzip2 в памяти.

Сообщение CynicRus » 29.10.2012 16:35:33

Доброго времени суток господа. Есть задача распаковать bz2 архив в память. Для этих целей пробую использовать TDecompressBzip2Stream класс.
Пробую следующую функцию:
Код: Выделить всё
procedure TDownloader.DecompressBZip2(const input: TStream; var res: TMemoryStream;
  const BlockSize: Cardinal);
var
  Unzipper : TDecompressBzip2Stream;
  Blocks : array of Byte;
  ReadSize : cardinal;
  i,j: integer;
begin
  SetLength(Blocks,BlockSize);
  try
    Unzipper := TDecompressBzip2Stream.Create(input);
  except
    on e : exception do
    begin;
  //    mDebugLn(e.message);
      exit;
    end;
  end;
  try
    repeat
      ReadSize := BlockSize;
      Unzipper.Read(blocks[0],readsize);  //Read ReadSize amount of bytes.
      Res.Write(Blocks[0],ReadSize);
    until readsize = 0;
  except
    on e : EBzip2 do
     if E.ErrCode <> bzip2_endoffile then
       raise Exception.CreateFmt('Decompression error: %s %d',[e.message,e.errcode]);
  end;
  Unzipper.Free;
end;
На вход её отдаю скачанный архив, пробовал его передавать как TFileStream и как TMemoryStream, но не зависимо от формы на строке Unzipper.Read(blocks[0],readsize); я падаю в SIGSEGV. При том что файл скачивается, я его уже даже на диск сохранял - всё равно падение происходит в указанном выше месте.
Что я делаю не так? И собственно вопрос - как скачанный tar.bz2 распаковать и полученный tar положить в другой TMemoryStream?

PS: Laz 0.9.30.4 , win 7, fpc 2.6.0.
CynicRus
постоялец
 
Сообщения: 106
Зарегистрирован: 28.06.2012 14:31:11

Re: Распаковка bzip2 в памяти.

Сообщение Vadim » 29.10.2012 17:07:05

CynicRus писал(а):Blocks : array of Byte;

Вы забыли создать массив, поэтому попадаете пальцем в небо на коде:
CynicRus писал(а):Unzipper.Read(blocks[0],readsize);
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Распаковка bzip2 в памяти.

Сообщение CynicRus » 29.10.2012 17:16:10

Так ведь инициализировал же я его при помощи SetLength(Blocks,BlockSize);...Разве нет?

Хотя даже если я делаю:
Blocks : array [0..4096] of Byte;

всё равно sigsegv.
CynicRus
постоялец
 
Сообщения: 106
Зарегистрирован: 28.06.2012 14:31:11

Re: Распаковка bzip2 в памяти.

Сообщение Vadim » 29.10.2012 20:25:47

А, извините, не увидел. :)
Тем не менее, всё равно Вы попадаете куда-то мимо выделенной памяти.
Вот, нашёл: Вы в переменную типа Byte читаете размер типа Cardinal, т.е. в один байт пытаетесь впихнуть четыре. Поэтому у программы сразу же случается выкидышь.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Распаковка bzip2 в памяти.

Сообщение iskander » 29.10.2012 20:48:06

Странный цикл:
Код: Выделить всё
    repeat
      ReadSize := BlockSize;
      Unzipper.Read(blocks[0],readsize);  //Read ReadSize amount of bytes.
      Res.Write(Blocks[0],ReadSize);
    until readsize = 0;

Ну с чего бы ReadSize прикидываться нулём? :wink:
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: Распаковка bzip2 в памяти.

Сообщение CynicRus » 30.10.2012 09:26:21

Vadim: ан нет, даже изменение типа массива - не помогло.

Для полноты картины привожу скриншот:
Изображение

Переписал вот так:
Код: Выделить всё
var
  Buffer: pointer;
  ReadSize: cardinal;
begin
  Getmem(Buffer, BlockSize);

  with TDecompressBzip2Stream.Create(input) do
  try
    repeat
      ReadSize := BlockSize;

      ReadSize := Read(Buffer^, ReadSize);

      if (ReadSize > 0) then
        Res.Write(Buffer^, ReadSize);
    until (ReadSize = 0);
  finally
    Free;
  end;

  Freemem(Buffer);
end;
но всё равно тот же сигсегв и в том же месте.

Добавлено спустя 2 часа 58 минут 9 секунд:
Вообщем в линуксе код работает прекрасно, а в винде почему-то необходимо выделить памяти на байт больше чем нужно, и тоже начинает работать прекрасно. Всем спасибо.
CynicRus
постоялец
 
Сообщения: 106
Зарегистрирован: 28.06.2012 14:31:11

Re: Распаковка bzip2 в памяти.

Сообщение Aleh » 31.01.2017 17:23:34

CynicRus писал(а):Вообщем в линуксе код работает прекрасно, а в винде почему-то необходимо выделить памяти на байт больше чем нужно, и тоже начинает работать прекрасно. Всем спасибо.
CynicRus
новенький
 
Сообщения: 72
Зарегистрирован: 28.06.2012 12:31:11

CynicRus писал(а):Вообщем в линуксе код работает прекрасно, а в винде почему-то необходимо выделить памяти на байт больше чем нужно, и тоже начинает работать прекрасно. Всем спасибо.


скорее всего BlockSize это High(Buffer), поэтому при выделении памяти нужно SetLength(Blocks,BlockSize+1);
То что в линуксе работало, вам "повезло"-запись портила не критичные области памяти (у меня, например, в вин7Х64 тоже работало нормально, а SIGSEGV был при закрытии проги)
в общем +1 НАДО!!!!! везде
Aleh
новенький
 
Сообщения: 53
Зарегистрирован: 08.08.2016 12:27:45


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 30

Рейтинг@Mail.ru