Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: ZLib usage IOS


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 2 - Last Post: Mar 29, 2018 1:55 PM Last Post By: William Brookfi... Threads: [ Previous | Next ]
William Brookfi...

Posts: 55
Registered: 1/1/10
ZLib usage IOS  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 26, 2018 12:23 PM
I have a need to compress and decompress string data.
I found 2 functions that work on my fmx app when comipled for win32 but not IOS.
I have tried playing with the tencoding values on the TStringStream.Create but no luck.
Anyone have a simple compress/decompress that works both IOS and WWin32?

Below are the functions that work in win32...

function ZCompressString(aText: string; aCompressionLevel: TZCompressionLevel): string;
var
  strInput,
  strOutput: TStringStream;
  Zipper: TZCompressionStream;
begin
  Result:= '';
  strInput:= TStringStream.Create(aText);
  strOutput:= TStringStream.Create;
  try
    Zipper:= TZCompressionStream.Create(strOutput);
    try
      Zipper.CopyFrom(strInput, strInput.Size);
    finally
      Zipper.Free;
    end;
    Result:= strOutput.DataString;
  finally
    strInput.Free;
    strOutput.Free;
  end;
end;
 
function ZDecompressString(aText: string): string;
var
  strInput,
  strOutput: TStringStream;
  Unzipper: TZDecompressionStream;
begin
  Result:= '';
  strInput:= TStringStream.Create(aText);
  strOutput:= TStringStream.Create;
  try
    Unzipper:= TZDecompressionStream.Create(strInput);
    try
      strOutput.CopyFrom(Unzipper, Unzipper.Size);
    finally
      Unzipper.Free;
    end;
    Result:= strOutput.DataString;
  finally
    strInput.Free;
    strOutput.Free;
  end;
end;
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: ZLib usage IOS  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 26, 2018 1:23 PM   in response to: William Brookfi... in response to: William Brookfi...
William Brookfield wrote:

I have a need to compress and decompress string data.
I found 2 functions that work on my fmx app when comipled for win32
but not IOS. I have tried playing with the tencoding values on the
TStringStream.Create but no luck.

Compression operates on bytes, not on characters, so you definately
need to deal with character encodings when compressing/decompressing
strings, especially Unicode strings. You must convert a string to
bytes first, then compress the bytes, then decompress the bytes, and
finally convert them back to a string.

Below are the functions that work in win32...

By default, when you don't specify a TEncoding to TStringStream, it
will use TEncoding.Default, which is ANSI on Windows but is UTF-8 on
other platforms. If you are trying to pass data between platforms, you
have to make sure that both platforms agree on a common encoding. In
this case, you should explicitly use UTF-8 on all platforms.

Also, compressed data is binary, not textual, so you can't store the
compressed data in a Unicode string, like you are trying to do.

Try something more like this instead:

type
  TBytesStreamAccess = class(TBytesStream)
  end;
 
function ZCompressString(const aText: string): TBytes;
var
  Input: TStringStream;
  Output: TBytesStream;
  Zipper: TZCompressionStream;
begin
  Result := nil;
  Output := TBytesStream.Create(nil);
  try
    Input := TStringStream.Create(aText, TEncoding.UTF8);
    try
      Zipper := TZCompressionStream.Create(Output);
      try
        Zipper.CopyFrom(Input, Input.Size);
      finally
        Zipper.Free;
      end;
    finally
      Input.Free;
    end;
    TBytesStreamAccess(Output).Capacity := Output.Size;
    Result := Output.Bytes;
  finally
    Output.Free;
  end;
end;
 
function ZDecompressString(const aText: TBytes): string;
var
  Input: TBytesStream;
  Output: TStringStream;
  Unzipper: TZDecompressionStream;
begin
  Result := '';
  Output := TStringStream.Create('', TEncoding.UTF8);
  try
    Input := TBytesStream.Create(aText);
    try
      Unzipper := TZDecompressionStream.Create(Input);
      try
        Output.CopyFrom(Unzipper, Unzipper.Size);
      finally
        Unzipper.Free;
      end;
    finally
      Input.Free;
    end;
    Result := Output.DataString;
  finally
    Output.Free;
  end;
end;


--
Remy Lebeau (TeamB)
William Brookfi...

Posts: 55
Registered: 1/1/10
Re: ZLib usage IOS  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 29, 2018 1:55 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
William Brookfield wrote:

I have a need to compress and decompress string data.
I found 2 functions that work on my fmx app when comipled for win32
but not IOS. I have tried playing with the tencoding values on the
TStringStream.Create but no luck.

Compression operates on bytes, not on characters, so you definately
need to deal with character encodings when compressing/decompressing
strings, especially Unicode strings. You must convert a string to
bytes first, then compress the bytes, then decompress the bytes, and
finally convert them back to a string.

Below are the functions that work in win32...

By default, when you don't specify a TEncoding to TStringStream, it
will use TEncoding.Default, which is ANSI on Windows but is UTF-8 on
other platforms. If you are trying to pass data between platforms, you
have to make sure that both platforms agree on a common encoding. In
this case, you should explicitly use UTF-8 on all platforms.

Also, compressed data is binary, not textual, so you can't store the
compressed data in a Unicode string, like you are trying to do.

Try something more like this instead:

type
  TBytesStreamAccess = class(TBytesStream)
  end;
 
function ZCompressString(const aText: string): TBytes;
var
  Input: TStringStream;
  Output: TBytesStream;
  Zipper: TZCompressionStream;
begin
  Result := nil;
  Output := TBytesStream.Create(nil);
  try
    Input := TStringStream.Create(aText, TEncoding.UTF8);
    try
      Zipper := TZCompressionStream.Create(Output);
      try
        Zipper.CopyFrom(Input, Input.Size);
      finally
        Zipper.Free;
      end;
    finally
      Input.Free;
    end;
    TBytesStreamAccess(Output).Capacity := Output.Size;
    Result := Output.Bytes;
  finally
    Output.Free;
  end;
end;
 
function ZDecompressString(const aText: TBytes): string;
var
  Input: TBytesStream;
  Output: TStringStream;
  Unzipper: TZDecompressionStream;
begin
  Result := '';
  Output := TStringStream.Create('', TEncoding.UTF8);
  try
    Input := TBytesStream.Create(aText);
    try
      Unzipper := TZDecompressionStream.Create(Input);
      try
        Output.CopyFrom(Unzipper, Unzipper.Size);
      finally
        Unzipper.Free;
      end;
    finally
      Input.Free;
    end;
    Result := Output.DataString;
  finally
    Output.Free;
  end;
end;


--
Remy Lebeau (TeamB)

Thank you Remy, I found some other code that works pretty similar to yours.

function ZCompressString(aText: string; aCompressionLevel: TZCompressionLevel): string;
var
  Utf8Stream: TStringStream;
  Compressed: TMemoryStream;
  Base64Stream: TStringStream;
begin
  Utf8Stream := TStringStream.Create(Atext, TEncoding.UTF8);
  try
    Compressed := TMemoryStream.Create;
    try
      ZCompressStream(Utf8Stream, Compressed, TZCompressionLevel.zcMax);
      Compressed.Position := 0;
      Base64Stream := TStringStream.Create('', TEncoding.ASCII);
      try
        EncodeStream(Compressed, Base64Stream);
        Result := Base64Stream.DataString;
      finally
        Base64Stream.Free;
      end;
    finally
      Compressed.Free;
    end;
  finally
    Utf8Stream.Free;
  end;
end;
 
function ZDecompressString(aText: string): string;
var
  Utf8Stream: TStringStream;
  Compressed: TMemoryStream;
  Base64Stream: TStringStream;
begin
  Base64Stream := TStringStream.Create(Atext, TEncoding.ASCII);
  try
    Compressed := TMemoryStream.Create;
    try
      DecodeStream(Base64Stream, Compressed);
      Compressed.Position := 0;
      Utf8Stream := TStringStream.Create('', TEncoding.UTF8);
      try
        ZDecompressStream(Compressed, Utf8Stream);
        Result := Utf8Stream.DataString;
      finally
        Utf8Stream.Free;
      end;
    finally
      Compressed.Free;
    end;
  finally
    Base64Stream.Free;
  end;
end;
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02