title: Delphi ZLib Compress / Decompress
body: <p>I've got a minor issue with decompressing using the ZLib unit in Delphi</p>
  
  <pre><code>unit uZCompression;
  
  interface
  
  uses
    uCompression;
  
  type
    TZZipCompression = class(TInterfacedObject, ICompression)
    public
      function DoCompression(aContent: TArray&lt;Byte&gt;): TArray&lt;Byte&gt;;
      function DoDecompression(aContent: TArray&lt;Byte&gt;): TArray&lt;Byte&gt;;
      function GetWindowsBits: Integer; virtual;
    end;
  
    TZGZipCompression = class(TZZipCompression)
      function GetWindowsBits: Integer; override;
    end;
  
  implementation
  
  uses
    System.ZLib, System.Classes, uMxKxUtils;
  
  { TZCompression }
  
  function TZZipCompression.DoCompression(aContent: TArray&lt;Byte&gt;): TArray&lt;Byte&gt;;
  var
    LContentStream, LOutputStream: TMemoryStream;
    LCompressedStream: TZCompressionStream;
  begin
    LContentStream := ByteArrayToStream(aContent);
  
    LOutputStream := TMemoryStream.Create;
  
    LCompressedStream := TZCompressionStream.Create(LOutputStream, zcDefault, GetWindowsBits);
    LCompressedStream.CopyFrom(LContentStream, LContentStream.Size);
    LCompressedStream.Free;
  
    Result := StreamToByteArray(LOutputStream);
  
    LOutputStream.Free;
    LContentStream.Free;
  end;
  
  function TZZipCompression.DoDecompression(aContent: TArray&lt;Byte&gt;): TArray&lt;Byte&gt;;
  var
    LContentStream, LOutputStream: TMemoryStream;
    LDecompressedStream: TZDecompressionStream;
  begin
    LContentStream := ByteArrayToStream(aContent);
  
    LOutputStream := TMemoryStream.Create;
  
    LDecompressedStream := TZDecompressionStream.Create(LContentStream);
    LOutputStream.CopyFrom(LDecompressedStream, LDecompressedStream.Size);
    LDecompressedStream.Free;
  
    Result := StreamToByteArray(LOutputStream);
  
    LOutputStream.Free;
    LContentStream.Free;
  end;
  
  function TZZipCompression.GetWindowsBits: Integer;
  begin
    Result := 15;
  end;
  
  { TZGZipCompression }
  
  function TZGZipCompression.GetWindowsBits: Integer;
  begin
    Result := inherited;
    Result := Result + 16;
  end;
  
  end.
  </code></pre>
  
  <p>This is my unit which is driven by an interface (which you don't need to know about), and data is passed in and out through a TArray variables.</p>
  
  <p>I've coded it to be able to do 2 types of compression, standard zip and gzip which is determined by the windowsbits passed in to the functions.</p>
  
  <p>Here are a couple of other functions being used to convert the TArray to TMemoryStream</p>
  
  <pre><code>function ByteArrayToStream(aContent: TArray&lt;Byte&gt;): TMemoryStream;
  begin
    Result := TMemoryStream.Create;
    Result.Write(aContent, length(aContent)*SizeOf(aContent[0]));
    Result.Position := 0;
  end;
  
  function StreamToByteArray(aStream: TMemoryStream): TArray&lt;Byte&gt;;
  var
    LStreamPos: Int64;
  begin
    if Assigned(aStream) then
    begin
      LStreamPos := aStream.Position;
      aStream.Position := 0;
      SetLength(Result, aStream.Size);
      aStream.Read(Result, aStream.Size);
      aStream.Position := LStreamPos;
    end
    else
      SetLength(Result, 0);
  end;
  </code></pre>
  
  <p>Now I can compress and decompress to .zip using the TZZipCompression class perfectly fine (it doesn't open up as a zip file, but it does decompress back to the original file which I can open and edit).</p>
  
  <p>I can also compress to .gz using the TZGZipCompression class fine as well (interestingly I can open this gzip file perfectly well).</p>
  
  <p>My issue however is that it won't decompress back from the .gz file and throws and error as soon as it hits</p>
  
  <pre><code>LOutputStream.CopyFrom(LDecompressedStream, LDecompressedStream.Size)
  </code></pre>
  
  <p>Funnily enough the Help file example has it as below</p>
  
  <pre><code>LOutputStream.CopyFrom(LDecompressedStream, 0)
  </code></pre>
  
  <p>But this doesn't work either.</p>
  
  <p>Can anyone spot the issue?</p>