You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

按Delphi帮助编写的zlib压缩无效,求可用gzip代码示例

问题原因

Embarcadero的示例代码生成的是原始zlib数据流,不是标准gzip格式。gzip有固定的文件头、CRC校验和原始长度尾段,这些是通用解压工具识别的关键标识;而原始zlib流仅包含压缩数据块,没有这些标准结构,所以只有Delphi自带的zlib工具能识别,其他通用工具(比如7-Zip、WinRAR)无法解析。

标准gzip格式的Delphi代码示例

以下代码基于Delphi自带的ZLib单元实现,无需第三方库,生成的gzip文件可被所有通用解压工具识别:

压缩为gzip格式

uses ZLib, Classes, SysUtils;

procedure CompressToGZip(const SourceFile, DestFile: string);
var
  SourceStream, DestStream: TFileStream;
  CompressStream: TZCompressionStream;
  GZipHeader: array[0..9] of Byte;
  CRC: Cardinal;
  UncompressedSize: Integer;
begin
  if not FileExists(SourceFile) then
    raise Exception.Create('源文件不存在');

  SourceStream := TFileStream.Create(SourceFile, fmOpenRead or fmShareDenyWrite);
  try
    DestStream := TFileStream.Create(DestFile, fmCreate or fmShareDenyWrite);
    try
      // 写入标准gzip文件头
      FillChar(GZipHeader, SizeOf(GZipHeader), 0);
      GZipHeader[0] := $1F; // gzip标识字节1
      GZipHeader[1] := $8B; // gzip标识字节2
      GZipHeader[2] := $08; // 压缩方式为DEFLATE
      GZipHeader[9] := $03; // 操作系统标识(Unix,可改为$00表示FAT/Windows)
      DestStream.WriteBuffer(GZipHeader, SizeOf(GZipHeader));

      // 初始化CRC32校验计算
      CRC := crc32(0, nil, 0);
      UncompressedSize := SourceStream.Size;

      // 创建压缩流并写入数据
      CompressStream := TZCompressionStream.Create(clMax, DestStream);
      try
        CRC := crc32(CRC, SourceStream.Memory, SourceStream.Size);
        CompressStream.CopyFrom(SourceStream, 0);
      finally
        CompressStream.Free;
      end;

      // 写入CRC校验值和原始文件大小(gzip标准要求)
      DestStream.WriteBuffer(CRC, SizeOf(CRC));
      DestStream.WriteBuffer(UncompressedSize, SizeOf(UncompressedSize));
    finally
      DestStream.Free;
    end;
  finally
    SourceStream.Free;
  end;
end;

解压gzip格式文件

uses ZLib, Classes, SysUtils;

procedure DecompressGZip(const SourceFile, DestFile: string);
var
  SourceStream, DestStream: TFileStream;
  DecompressStream: TZDecompressionStream;
  GZipHeader: array[0..9] of Byte;
  CRC, CheckCRC: Cardinal;
  UncompressedSize, CheckSize: Integer;
  ReadCount: Integer;
  Buffer: array[0..4095] of Byte;
begin
  if not FileExists(SourceFile) then
    raise Exception.Create('gzip源文件不存在');

  SourceStream := TFileStream.Create(SourceFile, fmOpenRead or fmShareDenyWrite);
  try
    // 读取并验证gzip文件头
    SourceStream.ReadBuffer(GZipHeader, SizeOf(GZipHeader));
    if (GZipHeader[0] <> $1F) or (GZipHeader[1] <> $8B) or (GZipHeader[2] <> $08) then
      raise Exception.Create('无效的gzip文件格式');

    // 跳过gzip头中的可选字段(简化处理,若需支持完整gzip标准可扩展)
    if (GZipHeader[3] and $04) <> 0 then // 存在额外字段
    begin
      var ExtraLen: Word;
      SourceStream.ReadBuffer(ExtraLen, SizeOf(ExtraLen));
      SourceStream.Seek(ExtraLen, soCurrent);
    end;
    if (GZipHeader[3] and $08) <> 0 then // 存在文件名
      while SourceStream.ReadByte <> 0 do;
    if (GZipHeader[3] and $10) <> 0 then // 存在注释
      while SourceStream.ReadByte <> 0 do;

    // 读取文件末尾的CRC校验值和原始文件大小
    SourceStream.Seek(-(SizeOf(CRC) + SizeOf(UncompressedSize)), soEnd);
    SourceStream.ReadBuffer(CheckCRC, SizeOf(CheckCRC));
    SourceStream.ReadBuffer(CheckSize, SizeOf(CheckSize));
    SourceStream.Seek(SizeOf(GZipHeader), soBeginning);

    // 解压数据并校验CRC
    DestStream := TFileStream.Create(DestFile, fmCreate or fmShareDenyWrite);
    try
      DecompressStream := TZDecompressionStream.Create(SourceStream);
      try
        CRC := crc32(0, nil, 0);
        repeat
          ReadCount := DecompressStream.Read(Buffer, SizeOf(Buffer));
          if ReadCount > 0 then
          begin
            CRC := crc32(CRC, @Buffer, ReadCount);
            DestStream.WriteBuffer(Buffer, ReadCount);
          end;
        until ReadCount = 0;

        // 验证CRC和文件大小
        if (CRC <> CheckCRC) or (DestStream.Size <> CheckSize) then
          raise Exception.Create('文件损坏或CRC校验失败');
      finally
        DecompressStream.Free;
      end;
    finally
      DestStream.Free;
    end;
  finally
    SourceStream.Free;
  end;
end;
使用示例
// 压缩
CompressToGZip('C:\test.txt', 'C:\test.txt.gz');
// 解压
DecompressGZip('C:\test.txt.gz', 'C:\test_uncompressed.txt');

内容的提问来源于stack exchange,提问作者Mikael

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 15:54:13