delphilzma解压示例

delphilzma解压示例,delphi,lzma,Delphi,Lzma,我在库的线程链接中找到了LZMA的实现。但我不能正确利用它的减压功能。 有人能用这个库为我写一个小的解压示例吗 这是我的代码,它适用于压缩,但不适用于解压缩并返回0大小 使用System.Zip.LZMA 我也试过这样做,但还是不行 procedure TForm2.Button2Click(Sender: TObject); var Deca: TLZMADecoderStream; Str1 : TMemoryStream; S2:TBytesStream; J, I: Card

我在库的线程链接中找到了LZMA的实现。但我不能正确利用它的减压功能。 有人能用这个库为我写一个小的解压示例吗

这是我的代码,它适用于压缩,但不适用于解压缩并返回0大小

使用System.Zip.LZMA

我也试过这样做,但还是不行

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;

你要求读取零字节,这就是你得到的。您需要循环读取流外的数据块。保持循环,直到
Read
返回零。请记住,
Read
返回读取的字节数

我会使用如下函数:

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;
这里绝对不需要内存流。需要两个文件流

您将面临的一个大问题是,您选择使用的库要求您知道要解压缩的文件有多大。如果试图读取的字节数超过可用字节数,则此库代码将进入非终止循环。因此,我的
Count
参数位于
LZMAdecompress

我怀疑您选择使用的库,或者至少您选择使用的类,不适合您的需要。我只是快速浏览了一下代码,但我觉得不太好。当呈现无效数据时,任何具有非终止循环的压缩库都不是很有用。我会根据这些证据避开这个图书馆。如果我是你,我会直接调用LZMA C API


也许您的另一个问题是您对正在使用的库进行了错误的更改。不要那样做。从github返回到原始版本

你从反编译流中读取了0个字节,你以为会发生什么<代码>J:=Deca.Read(S2.Bytes,0,i)。您初始化了
I:=0,从未更改它,因此从流中读取零字节。你得到了你想要的,AFAICT。所以我想你需要运行一个循环来读取块,直到Read返回0。您也做了许多Delphi程序员所做的事情,并感到必须不惜一切代价使用内存流。你正在读一个文件?使用TFileStream。不要先把它全部读入记忆。解压时,为什么要读入字节流,然后保存到文件中。直接读入以写模式打开的文件流。流是一个抽象层。也许你可以给出一个示例(请)我确信你可以将I设置为非零值。谢谢你,大卫!))对像我这样技术不高的家伙真的很有帮助
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;