Recent

Author Topic: [SOLVED] Zip/unzip String Function  (Read 14303 times)

DeBritto

  • Jr. Member
  • **
  • Posts: 68
[SOLVED] Zip/unzip String Function
« on: June 16, 2016, 03:18:46 pm »
Hi folks,

I'm looking for a piece of code (must be multiplatform) that could compress (like zip) and decompress a string. I've read something about paslib but it looks that it only handle with files. Best regards

I've found this code:

Code: Pascal  [Select][+][-]
  1. interface
  2.  
  3. uses
  4.   Classes, SysUtils, zlib;
  5.  
  6. function ZCompressString(aText: string; aCompressionLevel: TZCompressionLevel): string;
  7. function ZDecompressString(aText: string): string;
  8.  
  9. implementation
  10.  
  11. function ZCompressString(aText: string; aCompressionLevel: TZCompressionLevel): string;
  12. var
  13.   strInput,
  14.   strOutput: TStringStream;
  15.   Zipper: TZCompressionStream;
  16. begin
  17.   Result:= '';
  18.   strInput:= TStringStream.Create(aText);
  19.   strOutput:= TStringStream.Create;
  20.   try
  21.     Zipper:= TZCompressionStream.Create(strOutput, aCompressionLevel);
  22.     try
  23.       Zipper.CopyFrom(strInput, strInput.Size);
  24.     finally
  25.       Zipper.Free;
  26.     end;
  27.     Result:= strOutput.DataString;
  28.   finally
  29.     strInput.Free;
  30.     strOutput.Free;
  31.   end;
  32. end;
  33.  
  34. function ZDecompressString(aText: string): string;
  35. var
  36.   strInput,
  37.   strOutput: TStringStream;
  38.   Unzipper: TZDecompressionStream;
  39. begin
  40.   Result:= '';
  41.   strInput:= TStringStream.Create(aText);
  42.   strOutput:= TStringStream.Create;
  43.   try
  44.     Unzipper:= TZDecompressionStream.Create(strInput);
  45.     try
  46.       strOutput.CopyFrom(Unzipper, Unzipper.Size);
  47.     finally
  48.       Unzipper.Free;
  49.     end;
  50.     Result:= strOutput.DataString;
  51.   finally
  52.     strInput.Free;
  53.     strOutput.Free;
  54.   end;
  55. end;
  56.  

But when I try to compile it I receive this message:
Code: Pascal  [Select][+][-]
  1. uCompressionFunc.pas(10,60) Error: Identifier not found "TZCompressionLevel"
  2.  
« Last Edit: June 22, 2016, 07:44:29 pm by DeBritto »

BeniBela

  • Hero Member
  • *****
  • Posts: 926
    • homepage
Re: Zip/unzip String Function
« Reply #1 on: June 16, 2016, 03:45:40 pm »
I once wrote a Huffman encoder

But these encoders do not state-of-the-art compressions

ezlage

  • Guest
Re: Zip/unzip String Function
« Reply #2 on: June 16, 2016, 04:25:16 pm »
For compression, I use variants of this ancient code (written by me, in a specific case):
TEnhancedStream can be replaced by any stream type, and TEnhancedStream.Rewind is the same of Stream.Position:=0.

Code: Pascal  [Select][+][-]
  1. function DecompressStream(var Input: TEnhancedStream; var Output: TEnhancedStream): boolean;
  2. var
  3.   Decompressor: TDecompressionStream;
  4.   Buffer: array[$01..$400] of byte;
  5.   SwapStream: TEnhancedStream;
  6.   x: Int64=$00;
  7. begin
  8.   result:=False;
  9.   if Assigned(Input) and Assigned(Output)
  10.     then begin
  11.       Input.Rewind;
  12.       SwapStream:=TEnhancedStream.Create;
  13.       SwapStream.CopyFrom(Input,Input.Size);
  14.       SwapStream.Rewind;
  15.       Decompressor:=TDecompressionStream.Create(SwapStream);
  16.       Output.Clear;
  17.       repeat
  18.         x:=Decompressor.Read(Buffer{%H-},Length(Buffer));
  19.         if x>$00
  20.           then Output.Write(Buffer,x);
  21.       until x<=$00;
  22.       Decompressor.Free;
  23.       SwapStream.Free;
  24.       result:=True;
  25.     end;
  26. end;
  27.  
  28. function CompressStream(var Input: TEnhancedStream; var Output: TEnhancedStream): boolean;
  29. var
  30.   Compressor: TCompressionStream;
  31.   SwapStream: TEnhancedStream;
  32. begin
  33.   result:=False;
  34.   if Assigned(Input) and Assigned(Output)
  35.     then begin
  36.       Input.Rewind;
  37.       SwapStream:=TEnhancedStream.Create;
  38.       SwapStream.CopyFrom(Input,Input.Size);
  39.       Output.Clear;
  40.       Compressor:=TCompressionStream.Create(clMax,Output);
  41.       SwapStream.Rewind;
  42.       Compressor.CopyFrom(SwapStream,SwapStream.Size);
  43.       Compressor.Free;
  44.       SwapStream.Free;
  45.       result:=True;
  46.     end;
  47. end;
  48.  

ezlage

  • Guest
Re: Zip/unzip String Function
« Reply #3 on: June 16, 2016, 04:38:00 pm »
Hi folks,

I'm looking for a piece of code (must be multiplatform) that could compress (like zip) and decompress a string. I've read something about paslib but it looks that it only handle with files. Best regards

I've found this code:

Code: Pascal  [Select][+][-]
  1. interface
  2.  
  3. uses
  4.   Classes, SysUtils, zlib;
  5.  
  6. function ZCompressString(aText: string; aCompressionLevel: TZCompressionLevel): string;
  7. function ZDecompressString(aText: string): string;
  8.  
  9. implementation
  10.  
  11. function ZCompressString(aText: string; aCompressionLevel: TZCompressionLevel): string;
  12. var
  13.   strInput,
  14.   strOutput: TStringStream;
  15.   Zipper: TZCompressionStream;
  16. begin
  17.   Result:= '';
  18.   strInput:= TStringStream.Create(aText);
  19.   strOutput:= TStringStream.Create;
  20.   try
  21.     Zipper:= TZCompressionStream.Create(strOutput, aCompressionLevel);
  22.     try
  23.       Zipper.CopyFrom(strInput, strInput.Size);
  24.     finally
  25.       Zipper.Free;
  26.     end;
  27.     Result:= strOutput.DataString;
  28.   finally
  29.     strInput.Free;
  30.     strOutput.Free;
  31.   end;
  32. end;
  33.  
  34. function ZDecompressString(aText: string): string;
  35. var
  36.   strInput,
  37.   strOutput: TStringStream;
  38.   Unzipper: TZDecompressionStream;
  39. begin
  40.   Result:= '';
  41.   strInput:= TStringStream.Create(aText);
  42.   strOutput:= TStringStream.Create;
  43.   try
  44.     Unzipper:= TZDecompressionStream.Create(strInput);
  45.     try
  46.       strOutput.CopyFrom(Unzipper, Unzipper.Size);
  47.     finally
  48.       Unzipper.Free;
  49.     end;
  50.     Result:= strOutput.DataString;
  51.   finally
  52.     strInput.Free;
  53.     strOutput.Free;
  54.   end;
  55. end;
  56.  

But when I try to compile it I receive this message:
Code: Pascal  [Select][+][-]
  1. uCompressionFunc.pas(10,60) Error: Identifier not found "TZCompressionLevel"
  2.  

For your case, have no "TZCompressionLevel", I guess. You can declare it as integer in "type" section.
After, you must use this:

  Z_NO_COMPRESSION = 0;
  Z_BEST_SPEED = 1;
  Z_BEST_COMPRESSION = 9;
  Z_DEFAULT_COMPRESSION = -(1);

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Zip/unzip String Function
« Reply #4 on: June 16, 2016, 05:12:14 pm »
If you use the JCL unit Juha ported (see http://wiki.lazarus.freepascal.org/bzip2lib)
you can write string functions as follows, using the default "best compression" parameter = 9:

Code: Pascal  [Select][+][-]
  1.   function BZCompressString(const aText: string): string;
  2.   function BZDecompressString(const aText: string): string;
  3.  
  4. implementation
  5.  
  6. uses bzip2lib;
  7.  
  8. function BZCompressString(const aText: string): string;
  9. var
  10.   strInput, strOutput: TStringStream;
  11.   compressor: TBzip2CompressStream;
  12. begin
  13.   strInput:=TStringStream.Create(aText);
  14.   strOutput:=TStringStream.Create('');
  15.   try
  16.     compressor:=TBzip2CompressStream.Create(strOutput);
  17.     try
  18.       compressor.CopyFrom(strInput, strInput.Size);
  19.     finally
  20.       compressor.Free;
  21.     end;
  22.     Result:=strOutput.DataString;
  23.   finally
  24.     strOutput.Free;
  25.     strInput.Free;
  26.   end;
  27. end;
  28.  
  29. function BZDecompressString(const aText: string): string;
  30. var
  31.   strInput: TStringStream;
  32.   sl: TStringList;
  33.   decompressor: TBzip2DecompressStream;
  34. begin
  35.   strInput:=TStringStream.Create(aText);
  36.   sl:=TStringList.Create;
  37.   try
  38.     decompressor:=TBzip2DecompressStream.Create(strInput);
  39.     try
  40.       sl.LoadFromStream(decompressor);
  41.       Result:=sl.Text;
  42.     finally
  43.       decompressor.Free;
  44.     end;
  45.   finally
  46.     strInput.Free;
  47.     sl.Free;
  48.   end;
  49. end;                                      

Thaddy

  • Hero Member
  • *****
  • Posts: 16832
  • Ceterum censeo Trump esse delendam
Re: Zip/unzip String Function
« Reply #5 on: June 16, 2016, 06:12:48 pm »
I would take a look at http://www.oberhumer.com/opensource/ucl/
Very mature and multiple pascal interfaces available.
Changing servers. thaddy.com may be temporary unreachable but restored when the domain name transfer is done.

Arctic_Eddie

  • Jr. Member
  • **
  • Posts: 93
Re: Zip/unzip String Function
« Reply #6 on: June 16, 2016, 08:35:03 pm »
There is also the Abbrevia package available.

http://tpabbrevia.sourceforge.net/

sam707

  • Guest
Re: Zip/unzip String Function
« Reply #7 on: June 16, 2016, 09:38:19 pm »
I suggest you to look at this unit. might be useful

https://github.com/synopse/mORMot/blob/master/SynLZO.pas


there is also SynLZ.pas unit int the same github repo

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12162
  • FPC developer.
Re: Zip/unzip String Function
« Reply #8 on: June 17, 2016, 10:22:42 am »
Use the zstream unit that is part of paszlib. You can use that to compress streams (blocks of memory and strings), and as a bonus it is fairly delphi compatible. (though in unit "zlib" under delphi)

BeniBela

  • Hero Member
  • *****
  • Posts: 926
    • homepage
Re: Zip/unzip String Function
« Reply #9 on: June 17, 2016, 12:26:58 pm »
Now we need a benchmark, which one  makes the smallest files

And the size of the decompressor.

If you use it to compress resources, and it reduces the size by 10k, you would not want to include a 20k decompression lib

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12162
  • FPC developer.
Re: Zip/unzip String Function
« Reply #10 on: June 17, 2016, 12:41:26 pm »
Well, usually something zlib is also needed for e.g. HTTP, so it might already be in your components.

rvk

  • Hero Member
  • *****
  • Posts: 6711
Re: Zip/unzip String Function
« Reply #11 on: June 17, 2016, 12:49:07 pm »
Mmmm, Isn't blowfish mentioned here yet? (or is it too weak?)

See the thread:
http://forum.lazarus.freepascal.org/index.php/topic,19663.msg112190.html#msg112190

Standard in Lazarus and simple example:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$H+}
  2.  
  3. uses classes,blowfish,windows;
  4.  
  5. var
  6.   en: TBlowFishEncryptStream;
  7.   de: TBlowFishDeCryptStream;
  8.   s1,s2: TStringStream;
  9.   key,value,temp: String;
  10. begin
  11.   key := 'testkey';
  12.   value := 'this is a string';
  13.  
  14.   s1 := TStringStream.Create('');
  15.   en := TBlowFishEncryptStream.Create(key,s1);
  16.     en.Write(value[1],Length(value));
  17.   en.Free;
  18.  
  19.  
  20.   MessageBox(0,PChar(s1.DataString),'',MB_OK);
  21.   s2 := TStringStream.Create(s1.DataString);
  22.   s1.Free;
  23.  
  24.   de := TBlowFishDeCryptStream.Create(key,s2);
  25.  
  26.   SetLength(temp,s2.Size);
  27.   de.Read(temp[1],s2.Size);
  28.  
  29.   MessageBox(0,PChar(temp),'',MB_OK);
  30.   de.Free;
  31.  
  32.   s2.Free;
  33. end.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Zip/unzip String Function
« Reply #12 on: June 17, 2016, 01:09:00 pm »
DeBritto is not wanting to encrypt his string, but to compress/decompress it.

rvk

  • Hero Member
  • *****
  • Posts: 6711
Re: Zip/unzip String Function
« Reply #13 on: June 17, 2016, 01:14:29 pm »
DeBritto is not wanting to encrypt his string, but to compress/decompress it.
Woops, sorry. I seem to recall a topic, just yesterday about wanting to encrypt. But that was about a txt file. I'm a bit off today :)

DeBritto

  • Jr. Member
  • **
  • Posts: 68
Re: [SOLVED] Zip/unzip String Function
« Reply #14 on: June 22, 2016, 07:52:58 pm »
Hi folks,
Thank you for all your counsels. I checked all of them!

In my scenario, the "https://github.com/synopse/mORMot/blob/master/SynLZO.pas" worked liked a charm.

This is what I had to do:
1) copy SynLZO.pas and Synopse.inc to my application directory and include SynLZO unit inside my app.

2) To use the function This adjustment need to be made:
      CompressSynLZO( string_to_be_compreesed, true); 
      string_to_be_compressed := EncodeStringBase64(string_to_be_compressed);

If I do not do encode (base64) the string I receive "malformed string" error.
It was VERY hard to discover this. Thanks to MorMOT developers help in their forum.
:)

 Thank you guys, you Rock!

 

TinyPortal © 2005-2018