2015-05-20 52 views
-1

我在this找到delphi-zip庫的線程鏈接,該鏈接庫實現了LZMA。但我無法正確使用它的解壓縮。 有人可以使用這個庫爲我寫一個解壓縮示例嗎?德爾福LZMA解​​壓縮樣本

這裏是我的代碼,它適用於壓縮,但對於解壓沒有工作,返回0,大小

使用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; 

也是我試圖做這樣的,但還是不行

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; 
+2

您從解壓流中讀取0個字節,您預期會發生什麼? –

+1

'J:= Deca.Read(S2.Bytes,0,i);'。你初始化了'I:= 0;',從不改變它,因此從流中讀取零字節。你得到了你所要求的,AFAICT。 –

+0

所以我想你需要運行一個循環讀取塊,直到讀取返回0爲止。你也做了很多Delphi程序員所做的事情,並且不惜代價地使用內存流。你正在閱讀一個文件?使用TFileStream。不要先把它全部讀入內存。解壓時爲什麼要讀入字節流,然後保存到文件。直接讀入以寫入模式打開的文件流。流是一個抽象層。 –

回答

0

您要求讀零個字節,這就是你得到了什麼。您需要循環讀取數據流中的數據塊。保持循環,直到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

謝謝大衛!)))真的很有用像我這樣的低級技巧 –