Can Delphi JCL 7zCompression used to compress/decompress in-memory stream without file operations?
Asked Answered
P

1

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!

Psychological answered 9/8, 2011 at 14:28 Comment(2)
Does the 7z dll wrapper include stream functionality or callbacks somehow?Stelmach
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.Psychological
K
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;
Koral answered 9/8, 2011 at 15:6 Comment(2)
Perfect! I tested changing the Gzip to 7z and it work like a charm! Thank you very much!Psychological
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.Margherita

© 2022 - 2024 — McMap. All rights reserved.