2015-07-04 2 views
1

Я использую Delphi XE 8 и пытаюсь распаковать файл gzip. Я скопировал следующий код прямо с сайта Embarcadero в качестве примера, но я получаю «EZDecompressionError с сообщением„Ошибка данных“Delphi XE 8 - как распаковать файл gzip?

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; 

Пример файла Я пытаюсь распаковывать находится здесь:. http://ftp.nhc.noaa.gov/atcf/aid_public/

ответ

2

Ваш код верный, но вы забыли включить zlib для определения заголовка gzip (по умолчанию единственным форматом данных является формат zlib). Вы должны вызвать TDecompressionStream.Create(source: TStream; WindowBits: Integer) перегруженный конструктор и определить, насколько глубоко zlib должны смотреть на поток для gzip заголовка:

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; 

Для дальнейшей ссылки выглядят в zlib manual, также this question может быть полезным.

+0

Это похоже на очень хороший способ, +1 –

+0

@Free Consulting и Дэвид Хеффернан.Спасибо вам за помощь. Это был отличный опыт для меня. – Bryan

0

Вы пытаетесь обработать данные, как если бы они были сжатой Zlib. Однако это не совместимо с Gzip сжаты данными. Хотя оба формата использует один и тот же алгоритм внутреннего сжатия, они имеют разные заголовки.

распаковывать gzip Я ссылаюсь вы к этому вопросу: How to decode gzip data? Ответ Remy там объясняет, как вы можете использовать TIdCompressorZLib от Indy для распаковки данных gzip.

+0

Привет, Дэвид, спасибо за отзыв. Ссылка, которую вы предоставили, пролила некоторый свет на то, как это сделать, но я все еще застрял, так как не было примера. Ниже приводится моя реализация этого, но это не сработает. Я получаю TStream.Seek не реализована ошибка. Код в следующем комментарии – Bryan

+0

Процедура 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); // Получить файл в TStream h: = TIdIOHandlerStream.Create (GetFile, InStream, nil); GetFile.IOHandler: = h; DecompressedString: = GetFile.Get ('http: // nothing'); , наконец GetFile.Free; OutStream.Free; h.Free; InStream.Free; конец; конец; – Bryan

+0

@Bryan, не помещайте код в комментарии, [edit] (http://stackoverflow.com/posts/31221429/edit) свой вопрос и улучшайте его. – whosrdaddy

Смежные вопросы