8

I had used TJcl7zCompressArchive / TJcl7zDecompressArchive to do Archive operation before.

Now I would like to compress / decompress in-memory streams directly without file operation. However, when seeing the examples from JCL demos searching in the web, I cannot find a way to do so using that lib. I did find other tools to do that but the compression ratio seems not as good as 7zip.

Can anyone give some directions or sample code showing how to achieve this. Thanks a lot!

dsolimano
  • 8,870
  • 3
  • 48
  • 63
Justmade
  • 1,496
  • 11
  • 16
  • Does the 7z dll wrapper include stream functionality or callbacks somehow? – Warren P Aug 09 '11 at 14:34
  • There is instream/outstream as well as some callback objects. However, I can't figure out how and is it possible to use them directly without using those high level Achieve objects. – Justmade Aug 09 '11 at 14:50

1 Answers1

11

I use the JCL wrapper to compress a GZIP stream - not sure if it would work simply using a TJcl7ziCompresspArchive. To compress a stream I use the following:

procedure _CompressStreamGZIP( const ASourceStream, ADestinationStream: TStream );
var
  LArchive : TJclCompressArchive;
begin
  ADestinationStream.Position := 0;
  ASourceStream.Position := 0;
  LArchive := TJclGZipCompressArchive.Create( ADestinationStream, 0, False );

  try
    LArchive.AddFile( '..\Stream.0', ASourceStream, false );
    LArchive.Compress();
  finally
    if ( Assigned( LArchive ) ) then FreeAndNil( LArchive );
  end;
end;

To decompress the stream:

procedure _DecompressStreamGZIP( const ASourceStream, ADestinationStream : TStream );
var
  LArchive : TJclDecompressArchive;
begin
  ADestinationStream.Position := 0;
  ASourceStream.Position := 0;
  LArchive := TJclGZipDecompressArchive.Create( ASourceStream, 0, false );

  try
    LArchive.ListFiles();
    LArchive.Items[0].Stream := ADestinationStream;
    LArchive.Items[0].OwnsStream := false;
    LArchive.Items[0].Selected := True;
    LArchive.ExtractSelected();
  finally
    if ( Assigned( LArchive ) ) then FreeAndNil( LArchive );
  end;
end;
Fabricio Araujo
  • 3,810
  • 3
  • 28
  • 43
berndvf
  • 146
  • 1
  • 3
  • 1
    Perfect! I tested changing the Gzip to 7z and it work like a charm! Thank you very much! – Justmade Aug 09 '11 at 15:39
  • 4
    You should move the first three lines in the TRY/FINALLY block outside the TRY. In case an error occurs in the .Create constructor and an exception is raised, LArchive is unassigned (and is not NIL) and you then try to release an unallocated class instance. ALWAYS place the call to the constructor JUST before the TRY/FINALLY block that frees is. Also - you don't need to test for Assigned(LArchive) when calling FreeAndNIL, as this test is performed inside the FreeAndNIL procedure. – HeartWare Aug 09 '11 at 16:59