2015-05-20 3 views
-1

Я нашел в this нить ссылки библиотеки delphi-zip, которая имеет реализацию LZMA. Но я не могу правильно использовать Декомпрессию. Может ли кто-нибудь написать небольшой образец декомпрессии для меня, используя эту библиотеку?Delphi 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 байт из потока decomp, что вы ожидали? –

+1

'J: = Deca.Read (S2.Bytes, 0, i);'. Вы инициализировали 'I: = 0;', никогда не меняли его и поэтому читали нулевые байты из потока. У вас есть именно то, что вы просили, AFAICT. –

+0

Итак, я думаю, вам нужно запустить куски для чтения цикла, пока Read не вернет 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

Спасибо Дэвиду!))) Реально полезно для чувака, как я, с низким навыком –

Смежные вопросы