Delphi LZMA Decompression sample

旧巷老猫 提交于 2019-12-02 17:43:20

问题


I found in this thread link of the delphi-zip library that has implementation of LZMA. But I can't make proper use of Decompression from it. Can some one write a little decompression sample for me, using this library?

Here is my code, it works for compression but didn't work for decompression and return 0 size

uses System.Zip.LZMA;

....

procedure TForm2.CompressProgress(Sender: TObject; const aPosition, aSize, aCompressedSize: UInt64);
begin
end;

procedure TForm2.DecompressProgress(Sender: TObject; const aPosition, aSize: UInt64);
begin
end;

procedure TForm2.CompressButton1Click(Sender: TObject);
var LZI: TLZMAEncoderStream;  OutStream, InStream: TMemoryStream;
begin
     OutStream:= TMemoryStream.Create;
     LZI := TLZMAEncoderStream.Create(OutStream,  CompressProgress);
     InStream:= TMemoryStream.Create;
     InStream.LoadFromFile('1.exe');
     InStream.Position := 0;
     LZI.Write(InStream, InStream.Size);
     OutStream.Position := 0;
     OutStream.SaveToFile('1.exe.lzma');
     InStream.Free;
     OutStream.Free;
     LZI.Free;
end;

procedure TForm2.DecompressButton2Click(Sender: TObject);
var Deca: TLZMADecoderStream;    Str1: TMemoryStream; S2 : TBytesStream;  J, I: Cardinal;
begin
    I := 0;
    Str1 := TMemoryStream.Create;
    Str1.LoadFromFile('1.exe.lzma');
    Str1.Position := 0;
    Deca:= TLZMADecoderStream.Create(Str1, DecompressProgress);

   S2   := TBytesStream.Create;
   J := Deca.Read(S2.Bytes, 0, i);

    Caption := IntToStr(J);

   S2.Position := 0;
   S2.SaveToFile('1.exe');

   Deca.Free;
   Str1.Free;
   S2.Free;
end;

also I tried do like this, but still not work

procedure TForm2.Button2Click(Sender: TObject);
var Deca: TLZMADecoderStream;    Str1 : TMemoryStream;  S2:TBytesStream;  J, I: Cardinal;
begin
    I := 0;
    Str1 := TMemoryStream.Create;
    Str1.LoadFromFile('1.exe.lzma');
    Str1.Position := 0;
    Deca:= TLZMADecoderStream.Create(Str1, DeProgress);

   S2   := TBytesStream.Create;
   Deca.Position := 0;
   J := Deca.Read(S2.Bytes, 0, Deca.Size);
   Caption := IntToStr(J);
   S2.Position := 0;
   S2.SaveToFile('Dec0.exe');
   Deca.Free;
   Str1.Free;
   S2.Free;
end;

回答1:


You asked to read zero bytes and that's what you got. You will need to loop reading chunks of data out of the stream. Keep looping until Read returns zero. Remember that Read returns the number of bytes read.

I'd use functions like this:

procedure LZMAcompress(InStream, OutStream: TStream);
var
  Encoder: TLZMAEncoderStream;
begin
  Encoder := TLZMAEncoderStream.Create(OutStream, nil);
  try
    Encoder.Write(InStream, InStream.Size);
  finally
    Encoder.Free;
  end;
end;

procedure LZMAdecompress(InStream, OutStream: TStream; Count: Int64);
const
  BufferSize = 1024*1024;
var
  Decoder: TLZMADecoderStream;
  Buffer: TBytes;
  BytesRead, BytesToRead: Integer;
begin
  Decoder := TLZMADecoderStream.Create(InStream, nil);
  try
    SetLength(Buffer, BufferSize);
    repeat
      BytesToRead := Min(Count, BufferSize);
      BytesRead := Decoder.Read(Buffer, BytesToRead);
      OutStream.Write(Buffer, BytesRead);
      dec(Count, BytesRead);
    until Count=0;
  finally
    Decoder.Free;
  end;
end;

And there's absolutely no need for memory streams here. Two file streams are what is needed.

The big issue that you will face is that the library you have chosen to use requires you to know how large the file is that you are decompressing. If you try to read more bytes than are available, then this library code enters a non-terminating loop. Hence my Count parameter in LZMAdecompress.

My suspicion is that the library that you have chosen to use, or at least the classes that you have chosen to use, are ill suited to your needs. I've only had a quick look through the code but it doesn't look good to me. Any compression library that has a non-terminating loop when presented with invalid data is not very useful. I would shun this library on this evidence. If I were you I would call the LZMA C API directly.

Perhaps your other problem is that you have made erroneous changes to the library that you are using. Don't do that. Go back to the original version from github.



来源:https://stackoverflow.com/questions/30355553/delphi-lzma-decompression-sample

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!