⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lvkzlibutils.pas

📁 单独打包出来
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{******************************************************************************}
{*                                                                            *}
{* (C) Copyright 1999-2002, Lasse V錱s鎡her Karlsen                           *}
{*                                                                            *}
{******************************************************************************}

{ Description:
    This unit contains easy to use functions for compression and decompression
    through the zLib compression engine.

    Note: This is not a ZIP compression package, it will not handle .zip files,
      although the compression used is compatible with the one used in .zip
      files, the framework around the compressed data is missing.
}
unit lvkZLibUtils;

// $Author: Lasse V. Karlsen $
// $Date: 16.04.03 10:51 $
// $Revision: 10 $
// $Archive: /Components/LVK/source/lvkZLibUtils.pas $

interface

{$I VERSIONS.INC}
{$I DIRECTIVES.INC}

uses
  lvkZLib, lvkZLibConsts, SysUtils, Classes, lvkSafeMem, lvkTypes,
  lvkBufferedStream;

const
  DEFAULT_BUFFER_SIZE       = 32*1024;
  DEFAULT_WRITE_HEADER      = True;
  DEFAULT_READ_HEADER       = DEFAULT_WRITE_HEADER;
  DEFAULT_COMPRESSION_LEVEL = Z_BEST_COMPRESSION;

{ Description:
    This function compresses a file and stores the resulting data into another
    file.
  Parameters:
    SourceFileName - Full path and name of the file containing data to compress.
    SourceStream - The stream to read the uncompressed data from.
    Input - The string or memory block to read the uncompressed data to.
    DestinationFileName - Full path and name of the file to store the
      compressed data into.
    DestinationStream - The stream to write the compressed data to.
    CompressionLevel - How much work to put into compressing the data. More
      work results in smaller files, but will take slightly longer to process.
      The value range from 0 (no compression) to 9 (best compression). Default
      is to use the best compression level (ie. 9).
    BufferSize - How large input and output buffers to process the data through.
      Using larger buffers means more work can be done before having to transfer
      more data to/from the files, but will of course mean a higher memory
      total on your application.
    WriteHeader - Leave it to True to prepend a small header with information
      about the compression level and algorithm used to use as guidelines for
      the decompressor. Many programs, like WinZip and web browsers, doesn't
      use this header though.
  Returns:
    For the string and memory variants, the function returns the compressed
    stream or memory block.
  See also:
    zLibDecompress
}
procedure zLibCompress(const SourceFileName, DestinationFileName: string;
  const CompressionLevel: Integer=DEFAULT_COMPRESSION_LEVEL;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE;
  const WriteHeader: Boolean=DEFAULT_WRITE_HEADER); overload;

{ Description:
    This function decompresses a compressed file and stores the resulting data
    into another file.
  Parameters:
    SourceFileName - Full path and name of the file containing data to
      decompress.
    SourceStream - The stream to read the compressed data from.
    Input - The input memory or string to read the compressed data from.
    DestinationFileName - Full path and name of the file to store the
      decompressed data into.
    DestinationStream - The stream to write the decompressed data to.
    BufferSize - How large input and output buffers to process the data through.
      Using larger buffers means more work can be done before having to transfer
      more data to/from the files, but will of course mean a higher memory
      total on your application.
    ReadHeader - Leave it to True to be compatible with the .ZIP file format
      compression, set it to False to be compatible with the Deflate algorithm
      used with web browsers, and with the gzip file format. Note that this
      parameter must have the same value as the WriteHeader parameter you used
      with zLibCompressXYZ.
  Returns:
    For the string and memory variants, the function returns the decompressed
    stream or memory block.
  See also:
    zLibCompress
}
procedure zLibDecompress(const SourceFileName, DestinationFileName: string;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE;
  const ReadHeader: Boolean=DEFAULT_READ_HEADER); overload;

// <COMBINE zLibCompress@string@string@Integer@Cardinal@Boolean>
procedure zLibCompress(const SourceStream, DestinationStream: TStream;
  const CompressionLevel: Integer=DEFAULT_COMPRESSION_LEVEL;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE;
  const WriteHeader: Boolean=DEFAULT_WRITE_HEADER); overload;

// <COMBINE zLibDecompress@string@string@Cardinal@Boolean>
procedure zLibDecompress(const SourceStream, DestinationStream: TStream;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE;
  const ReadHeader: Boolean=DEFAULT_READ_HEADER); overload;

// <COMBINE zLibCompress@string@string@Integer@Cardinal@Boolean>
function zLibCompress(const Input: string;
  const CompressionLevel: Integer=DEFAULT_COMPRESSION_LEVEL;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE;
  const WriteHeader: Boolean=DEFAULT_WRITE_HEADER): string; overload;

// <COMBINE zLibDecompress@string@string@Cardinal@Boolean>
function zLibDecompress(const Input: string;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE;
  const ReadHeader: Boolean=DEFAULT_READ_HEADER): string; overload;

// <COMBINE zLibCompress@string@string@Integer@Cardinal@Boolean>
function zLibCompress(const Input: ISafeMem;
  const CompressionLevel: Integer=DEFAULT_COMPRESSION_LEVEL;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE;
  const WriteHeader: Boolean=DEFAULT_WRITE_HEADER): ISafeMem; overload;

// <COMBINE zLibDecompress@string@string@Cardinal@Boolean>
function zLibDecompress(const Input: ISafeMem;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE;
  const ReadHeader: Boolean=DEFAULT_READ_HEADER): ISafeMem; overload;

{ Description:
    This function compresses a file and stores the resulting data into another
    file. It uses the gzip compression format.
  Parameters:
    SourceFileName - Full path and name of the file containing data to compress.
    SourceStream - The stream to read the uncompressed data from.
    Input - The string or memory block to read the uncompressed data to.
    DestinationFileName - Full path and name of the file to store the
      compressed data into.
    DestinationStream - The stream to write the compressed data to.
    CompressionLevel - How much work to put into compressing the data. More
      work results in smaller files, but will take slightly longer to process.
      The value range from 0 (no compression) to 9 (best compression). Default
      is to use the best compression level (ie. 9).
    BufferSize - How large input and output buffers to process the data through.
      Using larger buffers means more work can be done before having to transfer
      more data to/from the files, but will of course mean a higher memory
      total on your application.
  Returns:
    For the string and memory variants, the function returns the compressed
    stream or memory block.
  See also:
    gZipDecompress
}
procedure gZipCompress(const SourceFileName, DestinationFileName: string;
  const CompressionLevel: Integer=DEFAULT_COMPRESSION_LEVEL;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE); overload;

{ Description:
    This function decompresses a compressed file and stores the resulting data
    into another file. It uses the gzip compression format.
  Parameters:
    SourceFileName - Full path and name of the file containing data to
      decompress.
    SourceStream - The stream to read the compressed data from.
    Input - The input memory or string to read the compressed data from.
    DestinationFileName - Full path and name of the file to store the
      decompressed data into.
    DestinationStream - The stream to write the decompressed data to.
    BufferSize - How large input and output buffers to process the data through.
      Using larger buffers means more work can be done before having to transfer
      more data to/from the files, but will of course mean a higher memory
      total on your application.
  Returns:
    For the string and memory variants, the function returns the decompressed
    stream or memory block.
  See also:
    gZipCompress
}
procedure gZipDecompress(const SourceFileName, DestinationFileName: string;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE); overload;

// <COMBINE gZipCompress@string@string@Integer@Cardinal>
procedure gZipCompress(const SourceStream, DestinationStream: TStream;
  const CompressionLevel: Integer=DEFAULT_COMPRESSION_LEVEL;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE); overload;

// <COMBINE gZipDecompress@string@string@Cardinal>
procedure gZipDecompress(const SourceStream, DestinationStream: TStream;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE); overload;

// <COMBINE gZipCompress@string@string@Integer@Cardinal>
function gZipCompress(const Input: string;
  const CompressionLevel: Integer=DEFAULT_COMPRESSION_LEVEL;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE): string; overload;

// <COMBINE gZipDecompress@string@string@Cardinal>
function gZipDecompress(const Input: string;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE): string; overload;

// <COMBINE gZipCompress@string@string@Integer@Cardinal>
function gZipCompress(const Input: ISafeMem;
  const CompressionLevel: Integer=DEFAULT_COMPRESSION_LEVEL;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE): ISafeMem; overload;

// <COMBINE gZipDecompress@string@string@Cardinal>
function gZipDecompress(const Input: ISafeMem;
  const BufferSize: Cardinal=DEFAULT_BUFFER_SIZE): ISafeMem; overload;

implementation

uses
  lvkZLibTypes, Windows, lvkCRC, lvkChecksumUtils;

type
  TGZipHeader = packed record
    ID1_2 : UInt16;
    CM    : UInt8;
    FLG   : UInt8;
    MTIME : UInt32;
    XFL   : UInt8;
    OS    : UInt8;
  end;

  TGZipTrailer = packed record
    CRC32 : TCRC32;
    ISIZE : UInt32;
  end;

const
  GZIP_FLAG_FTEXT     = 1;
  GZIP_FLAG_FHCRC     = 2;
  GZIP_FLAG_FEXTRA    = 4;
  GZIP_FLAG_FNAME     = 8;
  GZIP_FLAG_FCOMMENT  = 16;

  GZIP_SIGNATURE      = $8B1F;
  GZIP_DEFLATED       = 8;

procedure CompressStream(const SourceStream, DestinationStream: TStream;
  const CompressionLevel: Integer; const BufferSize: Cardinal;
  const WriteHeader: Boolean);
var
  zs            : z_stream;
  InputBuffer   : ISafeMem;
  OutputBuffer  : ISafeMem;
  errorCode     : Integer;
  AtEnd         : Boolean;

  procedure Initialize;
  begin
    ZeroMemory(@zs, SizeOf(zs));

    zs.next_in := InputBuffer.Pointer;
    zs.next_out := OutputBuffer.Pointer;
    zs.avail_out := OutputBuffer.Size;

    if WriteHeader then
      zLibCheckCompress(deflateInit(zs, CompressionLevel))
    else
      zLibCheckCompress(deflateInit2(zs, CompressionLevel, Z_DEFLATED, -15, 9,
        Z_DEFAULT_STRATEGY));
  end;

  procedure Cleanup;
  begin
    zLibCheckCompress(deflateEnd(zs));
  end;

begin
  Assert(Assigned(SourceStream));
  Assert(Assigned(DestinationStream));
  Assert((CompressionLevel >= -1) and (CompressionLevel <= 9));
  Assert(BufferSize >= 2048);

  InputBuffer := AllocateSafeMem(BufferSize);
  OutputBuffer := InputBuffer.Clone(False);

  Initialize;
  try
    AtEnd := False;

    repeat
      if zs.avail_in = 0 then
      begin
        zs.next_in := InputBuffer.Pointer;
        zs.avail_in := SourceStream.Read(zs.next_in^, InputBuffer.Size);
        if zs.avail_in < BufferSize then
          AtEnd := True;
      end;

      if AtEnd then
        errorCode := deflate(zs, Z_FINISH)
      else
        errorCode := deflate(zs, Z_NO_FLUSH);

      if (errorCode <> Z_STREAM_END) and (errorCode <> Z_OK) then
        zLibCheckCompress(errorCode);

      if (zs.avail_out = 0) or (errorCode = Z_STREAM_END) then
      begin
        DestinationStream.WriteBuffer(OutputBuffer.Pointer^, zs.next_out -
          OutputBuffer.Pointer);
        zs.next_out := OutputBuffer.Pointer;
        zs.avail_out := OutputBuffer.Size;
      end;
    until errorCode = Z_STREAM_END;
  finally
    Cleanup;
  end;
end;


procedure DecompressStream(const SourceStream, DestinationStream: TStream;
  const BufferSize: Cardinal; const ReadHeader: Boolean);
var
  zs            : z_stream;
  InputBuffer   : ISafeMem;
  OutputBuffer  : ISafeMem;
  errorCode     : Integer;

  procedure Initialize;
  begin
    ZeroMemory(@zs, SizeOf(zs));

    zs.next_in := InputBuffer.Pointer;
    zs.next_out := OutputBuffer.Pointer;
    zs.avail_out := OutputBuffer.Size;

    if ReadHeader then
      zLibCheckDecompress(inflateInit(zs))
    else
      zLibCheckDecompress(inflateInit2(zs, -15));
  end;

  procedure Cleanup;
  begin
    zLibCheckDecompress(inflateEnd(zs));
  end;

begin
  Assert(BufferSize >= 2048);

  InputBuffer := AllocateSafeMem(BufferSize);
  OutputBuffer := InputBuffer.Clone(False);

  Initialize;
  try
    repeat

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -