📄 jclcompression.pas
字号:
{**************************************************************************************************}
{ }
{ Project JEDI Code Library (JCL) }
{ }
{ The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
{ you may not use this file except in compliance with the License. You may obtain a copy of the }
{ License at http://www.mozilla.org/MPL/ }
{ }
{ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
{ ANY KIND, either express or implied. See the License for the specific language governing rights }
{ and limitations under the License. }
{ }
{ The Original Code is JclCompression.pas. }
{ }
{ The Initial Developer of the Original Code is Matthias Thoma. }
{ All Rights Reserved. }
{ }
{ Contributors: }
{ }
{**************************************************************************************************}
{ }
{ Alternatively, the contents of this file may be used under the terms of the GNU Lesser General }
{ Public License (the "LGPL License"), in which case the provisions of the LGPL License are }
{ applicable instead of those above. If you wish to allow use of your version of this file only }
{ under the terms of the LGPL License and not to allow others to use your version of this file }
{ under the MPL, indicate your decision by deleting the provisions above and replace them with the }
{ notice and other provisions required by the LGPL License. If you do not delete the provisions }
{ above, a recipient may use your version of this file under either the MPL or the LGPL License. }
{ }
{ For more information about the LGPL: }
{ http://www.gnu.org/copyleft/lesser.html }
{ }
{**************************************************************************************************}
{ }
{ This unit is still in alpha state. It is likely that it will change a lot. Suggestions are }
{ welcome. }
{ }
{**************************************************************************************************}
// Last modified: $Date: 2005/03/08 08:33:15 $
// For history see end of file
unit JclCompression;
interface
uses
{$IFDEF MSWINDOWS}
Windows,
{$ENDIF MSWINDOWS}
{$IFDEF UNIX}
Types,
{$ENDIF UNIX}
{$IFDEF HAS_UNIT_LIBC}
Libc,
{$ENDIF HAS_UNIT_LIBC}
SysUtils, Classes,
JclBase,
zlibh;
{**************************************************************************************************}
{
TJclCompressionStream
- -
----------------------- --------------------------
- -
TJclCompressStream TJclDecompressStream
- -
--------------------------------- ---------------------------------
- - - - - -
- - - - - -
TJclZLibCompressStream - TBZIP2CompressStram TJclZLibDecompressStream - TBZIP2DeCompressStream
- -
- TGZDecompressStream
TGZCompressStream
}
{**************************************************************************************************}
type
TJclCompressionStream = class(TStream)
private
FOnProgress: TNotifyEvent;
FBuffer: Pointer;
FBufferSize: Cardinal;
FStream: TStream;
protected
function SetBufferSize(Size: Cardinal): Cardinal; virtual;
procedure Progress(Sender: TObject); dynamic;
property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
public
constructor Create(Stream: TStream);
destructor Destroy; override;
function Read(var Buffer; Count: Longint): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
procedure Reset; virtual;
end;
TJclCompressStream = class(TJclCompressionStream)
public
function Flush: Integer; dynamic; abstract;
constructor Create(Destination: TStream);
end;
TJclDecompressStream = class(TJclCompressionStream)
public
constructor Create(Source: TStream);
end;
// ZIP Support
TJclCompressionLevel = Integer;
TJclZLibCompressStream = class(TJclCompressStream)
private
FWindowBits: Integer;
FMemLevel: Integer;
FMethod: Integer;
FStrategy: Integer;
FDeflateInitialized: Boolean;
FCompressionLevel: Integer;
protected
ZLibRecord: TZStreamRec;
procedure SetCompressionLevel(Value: Integer);
procedure SetStrategy(Value: Integer);
procedure SetMemLevel(Value: Integer);
procedure SetMethod(Value: Integer);
procedure SetWindowBits(Value: Integer);
public
constructor Create(Destination: TStream; CompressionLevel: TJclCompressionLevel = -1);
destructor Destroy; override;
function Flush: Integer; override;
procedure Reset; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
property WindowBits: Integer read FWindowBits write SetWindowBits;
property MemLevel: Integer read FMemLevel write SetMemLevel;
property Method: Integer read FMethod write SetMethod;
property Strategy: Integer read FStrategy write SetStrategy;
property CompressionLevel: Integer read FCompressionLevel write SetCompressionLevel;
end;
TJclZLibDecompressStream = class(TJclDecompressStream)
private
FWindowBits: Integer;
FInflateInitialized: Boolean;
protected
ZLibRecord: TZStreamRec;
procedure SetWindowBits(Value: Integer);
public
constructor Create(Source: TStream; WindowBits: Integer = DEF_WBITS);
destructor Destroy; override;
function Read(var Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
property WindowBits: Integer read FWindowBits write SetWindowBits;
end;
// GZIP Support
TJclGZIPCompressionStream = class(TJclCompressionStream)
end;
TJclGZIPDecompressionStream = class(TJclDecompressStream)
end;
// RAR Support
TJclRARCompressionStream = class(TJclCompressionStream)
end;
TJclRARDecompressionStream = class(TJclDecompressStream)
end;
// TAR Support
TJclTARCompressionStream = class(TJclCompressionStream)
end;
TJclTARDecompressionStream = class(TJclDecompressStream)
end;
// BZIP2 Support
(*
TJclBZIP2CompressStream = class(TJclCompressStream)
private
FDeflateInitialized: Boolean;
protected
BZLibRecord: TBZStream;
public
function Flush: Integer; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
constructor Create(Destination: TStream; CompressionLevel: TJclCompressionLevel = -1);
destructor Destroy; override;
end;
TJclBZIP2DecompressStream = class(TJclDecompressStream)
private
FInflateInitialized: Boolean;
protected
BZLibRecord: TBZStream;
public
function Read(var Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
constructor Create(Source: TStream); overload;
destructor Destroy; override;
end;
*)
EJclCompressionError = class(EJclError);
implementation
uses
JclResources;
const
JclDefaultBufferSize = 131072; // 128k
//=== { TJclCompressionStream } ==============================================
constructor TJclCompressionStream.Create(Stream: TStream);
begin
inherited Create;
FBuffer := nil;
SetBufferSize(JclDefaultBufferSize);
end;
destructor TJclCompressionStream.Destroy;
begin
SetBufferSize(0);
inherited Destroy;
end;
function TJclCompressionStream.Read(var Buffer; Count: Longint): Longint;
begin
raise EJclCompressionError.CreateRes(@RsCompressionReadNotSupported);
end;
function TJclCompressionStream.Write(const Buffer; Count: Longint): Longint;
begin
raise EJclCompressionError.CreateRes(@RsCompressionWriteNotSupported);
end;
function TJclCompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
begin
raise EJclCompressionError.CreateRes(@RsCompressionSeekNotSupported);
end;
procedure TJclCompressionStream.Reset;
begin
raise EJclCompressionError.CreateRes(@RsCompressionResetNotSupported);
end;
function TJclCompressionStream.SetBufferSize(Size: Cardinal): Cardinal;
begin
if FBuffer <> nil then
FreeMem(FBuffer, FBufferSize);
FBufferSize := Size;
if FBufferSize > 0 then
GetMem(FBuffer, FBufferSize)
else
FBuffer := nil;
Result := FBufferSize;
end;
procedure TJclCompressionStream.Progress(Sender: TObject);
begin
if Assigned(FOnProgress) then
FOnProgress(Sender);
end;
//=== { TJclCompressStream } =================================================
constructor TJclCompressStream.Create(Destination: TStream);
begin
inherited Create(Destination);
FStream := Destination;
end;
//=== { TJclDecompressStream } ===============================================
constructor TJclDecompressStream.Create(Source: TStream);
begin
inherited Create(Source);
FStream := Source;
end;
//=== { TJclZLibCompressionStream } ==========================================
{ Error checking helper }
function ZLibCheck(const ErrCode: Integer): Integer;
begin
Result := ErrCode;
if ErrCode < 0 then
case ErrCode of
Z_ERRNO:
raise EJclCompressionError.CreateRes(@RsCompressionZLibZErrNo);
Z_STREAM_ERROR:
raise EJclCompressionError.CreateRes(@RsCompressionZLibZStreamError);
Z_DATA_ERROR:
raise EJclCompressionError.CreateRes(@RsCompressionZLibZDataError);
Z_MEM_ERROR:
raise EJclCompressionError.CreateRes(@RsCompressionZLibZMemError);
Z_BUF_ERROR:
raise EJclCompressionError.CreateRes(@RsCompressionZLibZBufError);
Z_VERSION_ERROR:
raise EJclCompressionError.CreateRes(@RsCompressionZLibZVersionError);
else
raise EJclCompressionError.CreateRes(@RsCompressionZLibError);
end;
end;
constructor TJclZLibCompressStream.Create(Destination: TStream; CompressionLevel: TJclCompressionLevel);
begin
inherited Create(Destination);
Assert(FBuffer <> nil);
Assert(FBufferSize > 0);
// Initialize ZLib StreamRecord
with ZLibRecord do
begin
zalloc := nil; // Use build-in memory allocation functionality
zfree := nil;
next_in := nil;
avail_in := 0;
next_out := FBuffer;
avail_out := FBufferSize;
end;
FWindowBits := DEF_WBITS;
FMemLevel := DEF_MEM_LEVEL;
FMethod := Z_DEFLATED;
FStrategy := Z_DEFAULT_STRATEGY;
FCompressionLevel := CompressionLevel;
FDeflateInitialized := False;
end;
destructor TJclZLibCompressStream.Destroy;
begin
Flush;
if FDeflateInitialized then
begin
ZLibRecord.next_in := nil;
ZLibRecord.avail_in := 0;
ZLibRecord.avail_out := 0;
ZLibRecord.next_out := nil;
ZLibCheck(deflateEnd(ZLibRecord));
end;
inherited Destroy;
end;
function TJclZLibCompressStream.Write(const Buffer; Count: Longint): Longint;
begin
if not FDeflateInitialized then
begin
ZLibCheck(deflateInit(ZLibRecord, FCompressionLevel));
FDeflateInitialized := True;
end;
ZLibRecord.next_in := @Buffer;
ZLibRecord.avail_in := Count;
while ZLibRecord.avail_in > 0 do
begin
ZLibCheck(deflate(ZLibRecord, Z_NO_FLUSH));
if ZLibRecord.avail_out = 0 then // Output buffer empty. Write to stream and go on...
begin
FStream.WriteBuffer(FBuffer^, FBufferSize);
Progress(Self);
ZLibRecord.next_out := FBuffer;
ZLibRecord.avail_out := FBufferSize;
end;
end;
Result := Count;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -