TStreamMemory
델파이 CD의 Extras 폴더를 뒤져보면
ZLIb를 멋지게 포장한
TCompressionStream, TDecompressionStream 객체를 찾을 수 있다.
TStream을 간단히 압축하고 해제할 수 있게 해 주기 때문에 자주 애용하게 된다.
그런데, TStream이 아닌 그저 압축된 메모리 덩어리를 다뤄야 할 때는 어떻게 할까.
임시 스트림을 만들고 여기에 메모리를 옮겨담고 압축을 푼다??
뭔가 조금 어색하다.
메모리 덩어리를 굳이 복사하지 않고 스트림처럼 사용할 수는 없을까?
비슷한 경우는 또 있다.
버퍼에 옮긴 비트맵 파일.
여기 담겨있는 내용을 TBitmap의 LoadFromStream로 불러들일 수는 없을까?
TStreamMemory는 이런 고민이 생겼을 때 쓸만한 도구가 될 것이다.
동작 방법은 대충 다음과 같고...
StrmMem := TStreamMemory.Create(Buffer, BufferSize);
try
Bitmap.LoadFromStream(StrmMem);
finally
StrmMem.Free;
end;
이하는 소스코드. 짧은 내용이니 자세한 설명은 생략한다.
type
// 메모리를 스트림처럼 접근할 수 있는 녀석. 메모리스트림의 반대개념.
// 사이즈를 조절할 수 없다. 쓰기는 가능하지만 사이즈를 넘길 수 없다.
TStreamMemory = class(TStream)
private
fMemory: Pointer;
fSize, fPosition : Longint;
protected
public
constructor Create(const aMemory: Pointer; const aSize: Integer);
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 SetMemory(const aMemory: Pointer; const aSize: Integer);
procedure SaveToStream(Stream: TStream);
procedure SaveToFile(const FileName: string);
property Memory: Pointer read FMemory;
end;
....
{ TStreamMemory }
constructor TStreamMemory.Create(const aMemory: Pointer; const aSize: Integer);
begin
fMemory := aMemory;
fSize := aSize;
fPosition := 0;
end;
destructor TStreamMemory.Destroy;
begin
inherited;
end;
function TStreamMemory.Read(var Buffer; Count: Integer): 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 TStreamMemory.Write(const Buffer; Count: Integer): Longint;
var
Pos: Longint;
begin
Result := 0;
if (fPosition >= 0) and (Count >= 0) then
begin
Pos := fPosition + Count;
if Pos > Size then
begin
Pos := Size;
Count := Size - fPosition;
end;
System.Move(Buffer, Pointer(Longint(fMemory) + fPosition)^, Count);
fPosition := Pos;
Result := Count;
end;
end;
function TStreamMemory.Seek(Offset: Integer; Origin: Word): Longint;
begin
case Origin of
soFromBeginning : FPosition := Offset;
soFromCurrent : Inc(FPosition, Offset);
soFromEnd : FPosition := FSize + Offset;
end;
Result := FPosition;
end;
procedure TStreamMemory.SetMemory(const aMemory: Pointer; const aSize: Integer);
begin
fMemory := aMemory;
fSize := aSize;
fPosition := 0;
end;
procedure TStreamMemory.SaveToStream(Stream: TStream);
begin
if fSize <> 0 then Stream.WriteBuffer(fMemory^, fSize);
end;
procedure TStreamMemory.SaveToFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmCreate);
try
SaveToStream(Stream);
finally
Stream.Free;
end;
end
'Delphi Tip > +Tip' 카테고리의 다른 글
윈도우 바탕화면 경로(주소) 값 알아내기 (0) | 2022.02.11 |
---|---|
프로그램 중복 실행 방지 (0) | 2022.02.10 |
델파이 후킹(hooking) (0) | 2022.02.08 |
해당 월의 처음과 끝 날짜 알아오기 (0) | 2022.02.04 |
떠있는폼이 IsWindowEnabled인 상태 체크 (0) | 2022.02.03 |
댓글