Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2008-06

How to use TCompressionStream?

10 messages · 4 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Felipe Monteiro de Carvalho

Hello,

I am trying to use TCompressionStream to compress a string. But the destination stream is empty. Here is by code, thanks:

program stringcompressor;
{$apptype console}
uses
  Classes, SysUtils, zstream;
var
  Compressor: TCompressionStream;
  Source: TStringStream;
  Dest: TMemoryStream;
  i: Integer;
begin
  Source := TStringStream.Create('The string to be compressed');
  Dest := TMemoryStream.Create();
  Compressor := TCompressionStream.Create(clDefault, Dest);
  try
    Compressor.CopyFrom(Source, Source.Size);
    Write('The result is: ');
    Dest.Position := 0;
    for i := 0 to Dest.Size - 1 do
      IntToHex(Dest.ReadByte, 2);
    WriteLn('');
  finally
    Compressor.Free;
    Dest.Free;
    Source.Free;
  end;
end.

Reply by email

Joao Morais
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote 28 lines
Hello, I am trying to use TCompressionStream to compress a string. But the destination stream is empty. Here is by code, thanks: program stringcompressor; {$apptype console} uses Classes, SysUtils, zstream; var Compressor: TCompressionStream; Source: TStringStream; Dest: TMemoryStream; i: Integer; begin Source := TStringStream.Create('The string to be compressed'); Dest := TMemoryStream.Create(); Compressor := TCompressionStream.Create(clDefault, Dest); try Compressor.CopyFrom(Source, Source.Size); Write('The result is: '); Dest.Position := 0; for i := 0 to Dest.Size - 1 do IntToHex(Dest.ReadByte, 2);

What about use Compressor intead of Dest?

Joao Morais

Show quoted text 11 lines
WriteLn(''); finally Compressor.Free; Dest.Free; Source.Free; end; end. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Felipe Monteiro de Carvalho
to Marco van de Voort
Marco van de Voort wrote
Personally, I'd write() the strings that come from inttohex, instead of discarding them :_)

Indeed ... but that doesn't change anything =) It doesn't enter the loop ... I checked with the debugger.

What about use Compressor intead of Dest?

What is the use for Dest then if not to hold the destination data?

Also, I cannot use the Compressor because I cannot seek it and I cannot read it. I can only write to it.

thanks,

Felipe Monteiro de Carvalho

Reply by email

Michael Van Canneyt
to Felipe Monteiro de Carvalho: I am trying to use TCompressionStream to compress a string. But the destination stream is…
Felipe Monteiro de Carvalho wrote 23 lines
Hello, I am trying to use TCompressionStream to compress a string. But the destination stream is empty. Here is by code, thanks: program stringcompressor; {$apptype console} uses Classes, SysUtils, zstream; var Compressor: TCompressionStream; Source: TStringStream; Dest: TMemoryStream; i: Integer; begin Source := TStringStream.Create('The string to be compressed'); Dest := TMemoryStream.Create(); Compressor := TCompressionStream.Create(clDefault, Dest); try Compressor.CopyFrom(Source, Source.Size);

Call Compressor.flush first, only then all data will be in dest. This is done automatically when it is destroyed:

So it should also work if you destroy compressor prior to examining the result.

Michael.

Show quoted text 16 lines
Write('The result is: '); Dest.Position := 0; for i := 0 to Dest.Size - 1 do IntToHex(Dest.ReadByte, 2); WriteLn(''); finally Compressor.Free; Dest.Free; Source.Free; end; end. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Felipe Monteiro de Carvalho
to Michael Van Canneyt
Michael Van Canneyt wrote
Call Compressor.flush first, only then all data will be in dest. This is done automatically when it is destroyed:

There is no Compressor.Flush. But freeing it seams to work.

Now I am having trouble using TDecompressor. Should I use CopyFrom from another stream to get the decompressed data? This crashes the app. Also, CopyFrom expects the size, but I have no size ... I just want everything!

program stringcompressor;
{$apptype console}
uses
  Classes, SysUtils, zstream;
const
  Str_Original_String = 'The string to be compressed';
var
  Compressor: TCompressionStream;
  Decompressor: TDecompressionStream;
  StringStream: TStringStream;
  CompressedData: TMemoryStream;
  i: Integer;
begin
  WriteLn('The string to be compressed is: ', Str_Original_String);
  StringStream := TStringStream.Create(Str_Original_String);
  CompressedData := TMemoryStream.Create();
  Compressor := TCompressionStream.Create(clDefault, CompressedData);
  Decompressor := TDecompressionStream.Create(CompressedData);
  { Compress the string }
  Compressor.CopyFrom(StringStream, StringStream.Size);
  Compressor.Free;
  { Write the compressed string to the console }
  Write('The compressed data is: ');
  CompressedData.Position := 0;
  for i := 0 to CompressedData.Size - 1 do
    Write(IntToHex(CompressedData.ReadByte, 2));
  WriteLn('');
  { Decompress the string }
  StringStream.Size := 0;
  StringStream.CopyFrom(Decompressor, Decompressor.Size); // <----  crash
  WriteLn('The string after being compressed and decompressed is: ',
StringStream.DataString);
  Decompressor.Free;
  CompressedData.Free;
  StringStream.Free;
end.

Reply by email

Michael Van Canneyt
to Felipe Monteiro de Carvalho: On Sat, Jun 21, 2008 at 2:27 PM, Michael Van Canneyt There is no Compressor.Flush. But…
Felipe Monteiro de Carvalho wrote 6 lines
On Sat, Jun 21, 2008 at 2:27 PM, Michael Van Canneyt wrote: > Call Compressor.flush first, only then all data will be in dest. > This is done automatically when it is destroyed: There is no Compressor.Flush. But freeing it seams to work.

Copy & paste from zstream:

        Tcompressionstream=class(Tcustomzlibstream)
        protected
          raw_written,compressed_written:longint;
        public
          constructor create(level:Tcompressionlevel;
                             dest:Tstream;
                             Askipheader:boolean=false);
          destructor destroy;override;
          function write(const buffer;count:longint):longint;override;
          procedure flush; //// <-------------------- Flush ?
          function get_compressionrate:single;
        end;
Show quoted text 5 lines
Now I am having trouble using TDecompressor. Should I use CopyFrom from another stream to get the decompressed data? This crashes the app. Also, CopyFrom expects the size, but I have no size ... I just want everything!

You cannot use CopyFrom.
You must do a read till there is no data anymore.
See TStrings.LoadFromStream for instance.

Michael.

Reply by email

Felipe Monteiro de Carvalho
to Michael Van Canneyt
Michael Van Canneyt wrote
You cannot use CopyFrom. You must do a read till there is no data anymore. See TStrings.LoadFromStream for instance.

Indeed. TStrings.LoadFromStream works in the decompressor =)

thanks,

Felipe Monteiro de Carvalho

Reply by email