TMemoryStream 直接繼承 TCustomMemoryStream,繼承其屬性與方法。TCustomMemoryStream 為記憶體資料操作的抽象類別,提供框架;TMemoryStream 依動態記憶體管理需求填充具體實作。
TMemoryStream 在 protected 區新增 Capacity 屬性,決定記憶體串流佔用的動態記憶體大小。私有欄位 FCapacity 儲存屬性值,讀取直接回傳 FCapacity,寫入呼叫 SetCapacity:
property Capacity: Longint read FCapacity write SetCapacity;
procedure TMemoryStream.SetCapacity(NewCapacity: Longint); begin SetPointer(Realloc(NewCapacity), FSize); FCapacity := NewCapacity; end;
SetCapacity 先呼叫 Realloc 重新配置記憶體,再更新 FCapacity。Realloc 會處理物件狀態變更。
const
MemoryDelta = $2000; { 8K }
function TMemoryStream.Realloc(var NewCapacity: Longint): Pointer;
begin
if NewCapacity > 0 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);
if Result = nil then raise EStreamError.CreateRes(SMemoryStreamError);
end;
end;
end;
if 對齊邊界)。NewCapacity = 0:釋放記憶體(GlobalFreePtr)。Capacity = 0:配置新記憶體(GlobalAllocPtr)。GlobalReallocPtr)。Result = nil)拋出 EStreamError。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;
若寫入位置超出目前記憶體池,呼叫 SetCapacity 擴充,再以 System.Move 複製資料,更新位置指標並回傳寫入位元組數。FCapacity(配置容量)與 FSize(實際資料大小)不同。
procedure TMemoryStream.Clear; begin SetCapacity(0); FSize := 0; FPosition := 0; end;
釋放記憶體池,將 Memory 設為 nil,FSize 與 FPosition 歸零。
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;
LoadFromStream:依來源串流 Size 重新配置記憶體,呼叫來源 ReadBuffer 複製全部內容,形成完整拷貝。
LoadFromFile:建立 TFileStream 後呼叫 LoadFromStream,將檔案內容完整複製到記憶體串流。