1

I'm using Delphi XE 8 and trying to decompress a gzip file. I've copied the following code straight from the Embarcadero website as an example, but I get "EZDecompressionError with message 'data error'.

procedure DecompressGzip(inFileName : string);
var
  LInput, LOutput: TFileStream;
  LUnZip: TZDecompressionStream;

begin
  { Create the Input, Output, and Decompressed streams. }
  LInput := TFileStream.Create(InFileName, fmOpenRead);
  LOutput := TFileStream.Create(ChangeFileExt(InFileName, 'txt'), fmCreate);
  LUnZip := TZDecompressionStream.Create(LInput);

  { Decompress data. }
  LOutput.CopyFrom(LUnZip, 0);
  { Free the streams. }
  LUnZip.Free;
  LInput.Free;
  LOutput.Free;
end;

An example file I'm trying to decompress is located here: http://ftp.nhc.noaa.gov/atcf/aid_public/

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Bryan
  • 81
  • 2
  • 8

2 Answers2

4

Your code is correct, but you've forgot to enable zlib to detect gzip header (by default, the only data format recognized is zlib format). You have to call TDecompressionStream.Create(source: TStream; WindowBits: Integer) overloaded constructor and specify how deep zlib should look into stream for gzip header:

procedure TForm2.FormCreate(Sender: TObject);
var
  FileStream: TFileStream;
  DecompressionStream: TDecompressionStream;
  Strings: TStringList;
begin
  FileStream := TFileStream.Create('aal012015.dat.gz', fmOpenRead);
{
     windowBits can also be greater than 15 for optional gzip decoding.  Add
   32 to windowBits to enable zlib and gzip decoding with automatic header
   detection, or add 16 to decode only the gzip format (the zlib format will
   return a Z_DATA_ERROR).
}
  DecompressionStream := TDecompressionStream.Create(FileStream, 15 + 16);  // 31 bit wide window = gzip only mode

  Strings := TStringList.Create;
  Strings.LoadFromStream(DecompressionStream);

  ShowMessage(Strings[0]);

  { .... }
end;

For further reference look into zlib manual, also this question might be useful.

Community
  • 1
  • 1
Free Consulting
  • 4,300
  • 1
  • 29
  • 50
  • @Free Consulting and David Heffernan. Thank you both for your help. This was a great learning experience for me. – Bryan Jul 05 '15 at 13:27
0

You are attempting to treat the data as though it were zlib compressed. However that is not compatible with gzip compressed data. Although both formats use the same internal compression algorithm, they have different headers.

To decompress gzip I refer you to this question: How to decode gzip data? Remy's answer there explains how you can use the TIdCompressorZLib from Indy to decompress gzip data.

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Hi David, thanks for the tip. The link you provided did shed some light on how to do it, but I'm still stuck since there was not an example. Below is my implementation of this, but it doesn't work. I get TStream.Seek not implemented error. Code in next comment – Bryan Jul 04 '15 at 15:34
  • Procedure DownloadAndDecompressGzip(inURL, SaveName : String); var GetFile: TIdHTTP; DecompressedString: String; h : TidIOHandlerStream; OutStream, InStream : TStream; begin GetFile := TIdHTTP.Create(nil); OutStream := TStream.Create; InStream := TStream.Create; try GetFile.Get(inURL, InStream); //Retrieve the file to TStream h := TIdIOHandlerStream.Create(GetFile, InStream, nil); GetFile.IOHandler := h; DecompressedString := GetFile.Get('http://nothing'); finally GetFile.Free; OutStream.Free; h.Free; InStream.Free; end; end; – Bryan Jul 04 '15 at 15:36
  • @Bryan, do not put code into comments, [edit](http://stackoverflow.com/posts/31221429/edit) your question and improve it instead. – whosrdaddy Jul 04 '15 at 17:53
  • The question is fine. It's perhaps too much to expect us to answer the next q too. – David Heffernan Jul 04 '15 at 18:15
  • @whosrdaddy Thanks. New to stackoverflow and it didn't jump out at me that I should just edit the original. I was wondering why I couldn't do a full reply.... – Bryan Jul 04 '15 at 18:40
  • It's good to edit a question to clarify. But it's not right to edit and change the question, asking a new question, and invalidating the answers. I rolled back your edit. – David Heffernan Jul 04 '15 at 19:16
  • Ok, thanks David. I guess I need to read the rules for this site again. ;) I was taking the advice of @whosrdaddy to "improve" my question with the guidance you pointed me to from Remey, but I guess that will not work... I guess I'll do some reading on the Indy site and more on TStreams. Maybe even check out the Emb forums (if they are up and running). – Bryan Jul 04 '15 at 21:31