📄 compressionstreamunit.pas
字号:
try
while Count <> 0 do
begin
if Count > BufSize then N := BufSize else N := Count;
Source.ReadBuffer(Buffer^, N);
WriteBuffer(Buffer^, N);
Dec(Count, N);
end;
finally
FreeMem(Buffer, BufSize);
end;
end;
constructor THandleStream.Create(AHandle: Integer);
begin
inherited Create;
FHandle := AHandle;
end;
function THandleStream.Read(var Buffer; Count: Longint): Longint;
begin
Result := FileRead(FHandle, Buffer, Count);
if Result = -1 then Result := 0;
end;
function THandleStream.Write(const Buffer; Count: Longint): Longint;
begin
Result := FileWrite(FHandle, Buffer, Count);
if Result = -1 then Result := 0;
end;
function THandleStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
begin
Result := FileSeek(FHandle, Offset, Ord(Origin));
end;
procedure THandleStream.SetSize(NewSize: Longint);
begin
SetSize(Int64(NewSize));
end;
procedure THandleStream.SetSize(const NewSize: Int64);
begin
Seek(NewSize, soBeginning);
end;
constructor TFileStream.Create(const FileName: string; Mode: Word);
begin
Create(Filename, Mode, 0);
end;
constructor TFileStream.Create(const FileName: string; Mode: Word; Rights: Cardinal);
begin
if Mode = $FFFF then
begin
inherited Create(FileCreate(FileName));
end
else
begin
inherited Create(FileOpen(FileName, Mode));
end;
end;
destructor TFileStream.Destroy;
begin
if FHandle >= 0 then FileClose(FHandle);
inherited Destroy;
end;
constructor TCustomCompressionStream.Create(Stream: TStream);
begin
inherited Create;
FStream := Stream;
FStreamPos := Stream.Position;
end;
procedure TCustomCompressionStream.DoProgress;
begin
if Assigned(FOnProgress) then FOnProgress(Self);
end;
constructor TCompressionStream.Create(Dest: TStream; CompressionLevel: TCompressionLevel);
begin
inherited Create(dest);
FStreamRecord.NextOut := FBuffer;
FStreamRecord.AvailableOut := SizeOf(FBuffer);
DeflateInit(FStreamRecord, Levels[CompressionLevel]);
end;
destructor TCompressionStream.Destroy;
begin
FStreamRecord.NextIn := nil;
FStreamRecord.AvailableIn := 0;
try
if FStream.Position <> FStreamPos then FStream.Position := FStreamPos;
while deflate(FStreamRecord, 4) <> 1 do
begin
FStream.WriteBuffer(FBuffer, SizeOf(FBuffer) - FStreamRecord.AvailableOut);
FStreamRecord.NextOut := FBuffer;
FStreamRecord.AvailableOut := SizeOf(FBuffer);
end;
if FStreamRecord.AvailableOut < SizeOf(FBuffer) then
begin
FStream.WriteBuffer(FBuffer, SizeOf(FBuffer) - FStreamRecord.AvailableOut);
end;
finally
deflateEnd(FStreamRecord);
end;
inherited Destroy;
end;
function TCompressionStream.Read(var Buffer; Count: longint): longint;
begin
end;
function TCompressionStream.Write(const Buffer; Count: longint): longint;
begin
FStreamRecord.NextIn := @Buffer;
FStreamRecord.AvailableIn := Count;
if FStream.Position <> FStreamPos then FStream.Position := FStreamPos;
while FStreamRecord.AvailableIn > 0 do
begin
deflate(FStreamRecord, 0);
if FStreamRecord.AvailableOut = 0 then
begin
FStream.WriteBuffer(FBuffer, SizeOf(FBuffer));
FStreamRecord.NextOut := FBuffer;
FStreamRecord.AvailableOut := SizeOf(FBuffer);
FStreamPos := FStream.Position;
DoProgress;
end;
end;
Result := Count;
end;
function TCompressionStream.Seek(offset: Longint; origin: Word): Longint;
begin
if (offset = 0) and (origin = soFromCurrent) then
begin
Result := FStreamRecord.TotalIn;
end;
end;
function TCompressionStream.GetCompressionRate: Single;
begin
if FStreamRecord.TotalIn = 0 then Result := 0
else Result := (1.0 - (FStreamRecord.TotalOut / FStreamRecord.TotalIn)) * 100.0;
end;
constructor TDecompressionStream.Create(source: TStream);
begin
inherited Create(source);
FStreamRecord.NextIn := FBuffer;
FStreamRecord.AvailableIn := 0;
InflateInit(FStreamRecord);
end;
destructor TDecompressionStream.Destroy;
begin
inflateEnd(FStreamRecord);
inherited Destroy;
end;
function TDecompressionStream.Read(var Buffer; Count: longint): longint;
var
ReturnValue: longint;
begin
FStreamRecord.NextOut := @Buffer;
FStreamRecord.AvailableOut := Count;
if FStream.Position <> FStreamPos then FStream.Position := FStreamPos;
ReturnValue := 0;
while ((FStreamRecord.AvailableOut > 0) and (ReturnValue <> 1)) do
begin
if FStreamRecord.AvailableIn = 0 then
begin
FStreamRecord.AvailableIn := FStream.Read(FBuffer, SizeOf(FBuffer));
if FStreamRecord.AvailableIn = 0 then
begin
Result := Count - FStreamRecord.AvailableOut;
Exit;
end;
FStreamRecord.NextIn := FBuffer;
FStreamPos := FStream.Position;
DoProgress;
end;
ReturnValue := inflate(FStreamRecord, 0);
end;
if ((ReturnValue = 1) and (FStreamRecord.AvailableIn > 0)) then
begin
FStream.Position := FStream.Position - FStreamRecord.AvailableIn;
FStreamPos := FStream.Position;
FStreamRecord.AvailableIn := 0;
end;
Result := Count - FStreamRecord.AvailableOut;
end;
function TDecompressionStream.Write(const Buffer; Count: longint): longint;
begin
end;
function TDecompressionStream.Seek(Offset: longint; Origin: Word): longint;
var
Buffer: array [0..8191] of Char;
Count: Integer;
begin
if ((Offset = 0) and (Origin = soFromBeginning)) then
begin
inflateReset(FStreamRecord);
FStreamRecord.NextIn := FBuffer;
FStreamRecord.AvailableIn := 0;
FStream.Position := 0;
FStreamPos := 0;
end
else if ((Offset >= 0) and (Origin = soFromCurrent)) or (((Offset - FStreamRecord.TotalOut) > 0) and (Origin = soFromBeginning)) then
begin
if Origin = soFromBeginning then Dec(Offset, FStreamRecord.TotalOut);
if Offset > 0 then
begin
for Count := 1 to Offset div SizeOf(Buffer) do ReadBuffer(Buffer, SizeOf(Buffer));
ReadBuffer(Buffer, Offset mod SizeOf(Buffer));
end;
end
else if (Offset = 0) and (Origin = soFromEnd) then
begin
while Read(Buffer, SizeOf(Buffer)) > 0 do;
end;
Result := FStreamRecord.TotalOut;
end;
procedure TCustomMemoryStream.SetPointer(Ptr: Pointer; Size: Longint);
begin
FMemory := Ptr;
FSize := Size;
end;
function TCustomMemoryStream.Read(var Buffer; Count: Longint): Longint;
begin
if (FPosition >= 0) and (Count >= 0) then
begin
Result := FSize - FPosition;
if Result > 0 then
begin
if Result > Count then Result := Count;
Move(Pointer(Longint(FMemory) + FPosition)^, Buffer, Result);
Inc(FPosition, Result);
Exit;
end;
end;
Result := 0;
end;
function TCustomMemoryStream.Seek(Offset: Longint; Origin: Word): Longint;
begin
case Origin of
soFromBeginning: FPosition := Offset;
soFromCurrent: Inc(FPosition, Offset);
soFromEnd: FPosition := FSize + Offset;
end;
Result := FPosition;
end;
procedure TCustomMemoryStream.SaveToStream(Stream: TStream);
begin
if FSize <> 0 then Stream.WriteBuffer(FMemory^, FSize);
end;
procedure TCustomMemoryStream.SaveToFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmCreate);
try
SaveToStream(Stream);
finally
Stream.Free;
end;
end;
const
MemoryDelta = $2000;
destructor TMemoryStream.Destroy;
begin
Clear;
inherited Destroy;
end;
procedure TMemoryStream.Clear;
begin
SetCapacity(0);
FSize := 0;
FPosition := 0;
end;
procedure TMemoryStream.LoadFromStream(Stream: TStream);
var
Count: Longint;
begin
Stream.Position := 0;
Count := Stream.Size;
SetSize(Count);
if Count <> 0 then Stream.ReadBuffer(FMemory^, Count);
end;
procedure TMemoryStream.LoadFromFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
LoadFromStream(Stream);
finally
Stream.Free;
end;
end;
procedure TMemoryStream.SetCapacity(NewCapacity: Longint);
begin
SetPointer(Realloc(NewCapacity), FSize);
FCapacity := NewCapacity;
end;
procedure TMemoryStream.SetSize(NewSize: Longint);
var
OldPosition: Longint;
begin
OldPosition := FPosition;
SetCapacity(NewSize);
FSize := NewSize;
if OldPosition > NewSize then Seek(0, soFromEnd);
end;
function TMemoryStream.Realloc(var NewCapacity: Longint): Pointer;
begin
if (NewCapacity > 0) and (NewCapacity <> FSize) then
NewCapacity := (NewCapacity + (MemoryDelta - 1)) and not (MemoryDelta - 1);
Result := Memory;
if NewCapacity <> FCapacity then
begin
if NewCapacity = 0 then
begin
GlobalFreePtr(Memory);
Result := nil;
end else
begin
if Capacity = 0 then
Result := GlobalAllocPtr(HeapAllocFlags, NewCapacity)
else
Result := GlobalReallocPtr(Memory, NewCapacity, HeapAllocFlags);
end;
end;
end;
function TMemoryStream.Write(const Buffer; Count: Longint): Longint;
var
Pos: Longint;
begin
if (FPosition >= 0) and (Count >= 0) then
begin
Pos := FPosition + Count;
if Pos > 0 then
begin
if Pos > FSize then
begin
if Pos > FCapacity then
SetCapacity(Pos);
FSize := Pos;
end;
System.Move(Buffer, Pointer(Longint(FMemory) + FPosition)^, Count);
FPosition := Pos;
Result := Count;
Exit;
end;
end;
Result := 0;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -