在 VCL 流體系中,TFileStream 與 THandleStream 是磁盤文件與內核句柄資源的兩大核心入口。前者封裝文件名與打開模式,後者直接持有 HANDLE,支援管道、郵槽、設備介面等任意內核對象。本文詳解類結構、關鍵參數、異常安全模式與高性能讀寫模式。
TObject
└── TStream
└── THandleStream
└── TFileStream
TStream:抽象基類,定義 Read/Write/Seek/Position/Size 核心介面。THandleStream:持有 HANDLE,直接委派 ReadFile/WriteFile/SetFilePointer。TFileStream:在 THandleStream 基礎上增加 FileName、Mode 管理,構造時自動 CreateFile,析構時自動 CloseHandle。__fastcall TFileStream(const AnsiString FileName, Word Mode);
Mode = OpenMode | ShareMode,位或組合:
| 類別 | 常數 | 值(十六進制) | 語義 |
|---|---|---|---|
| OpenMode | fmCreate | 0xFF00 | 建新/覆蓋舊檔 |
fmOpenRead | 0x0000 | 唯讀 | |
fmOpenWrite | 0x0001 | 寫入(截斷) | |
fmOpenReadWrite | 0x0002 | 讀寫不截斷 | |
| ShareMode | fmShareCompat | 0x0000 | FCB 相容(舊) |
fmShareExclusive | 0x0010 | 獨佔 | |
fmShareDenyWrite | 0x0020 | 拒寫共享 | |
fmShareDenyRead | 0x0030 | 拒讀共享 | |
fmShareDenyNone | 0x0040 | 全共享 |
常用組合:
fmCreate | fmShareDenyNone(建新全共享)
fmOpenRead | fmShareDenyNone(唯讀全共享)
fmOpenReadWrite | fmShareDenyWrite(讀寫獨寫)
__fastcall THandleStream(int Handle);
CreateFile、CreatePipe、CreateNamedPipe、CreateMailslot、socket() 等已獲取 HANDLE 的場景。Handle 唯讀屬性暴露底層句柄,不可修改;需切換模式時必須 delete stream; CloseHandle(h); h = CreateFile(...); stream = new THandleStream(h);。Size 屬性可讀寫,寫入即呼叫 SetEndOfFile 截斷/擴展;唯讀句柄設 Size 會拋異常。| 方法 | 簽名 | 語義 |
|---|---|---|
Read | virtual int __fastcall Read(void* Buffer, int Count) | 讀最多 Count 位元組,返回實讀字節數 |
Write | virtual int __fastcall Write(const void* Buffer, int Count) | 寫 Count 位元組,返回實寫字節數 |
Seek | virtual int __fastcall Seek(int Offset, Word Origin) | 移動指標,Origin: soFromBeginning/soFromCurrent/soFromEnd |
SetSize | virtual void __fastcall SetSize(int NewSize) | 截斷/擴展流 |
高層封裝:ReadBuffer/WriteBuffer(不足拋異常)、ReadComponent/WriteComponent(組件序列化)、CopyFrom(流間高效複製)。
class ScopedFileStream {
TFileStream* fs;
public:
ScopedFileStream(const AnsiString& fn, Word mode) : fs(new TFileStream(fn, mode)) {}
~ScopedFileStream() { delete fs; }
TFileStream* operator->() { return fs; }
TFileStream& operator*() { return *fs; }
};
// 使用
{
ScopedFileStream s("data.bin", fmOpenRead | fmShareDenyNone);
int count;
s->ReadBuffer(&count, sizeof(count));
std::vector<char> buf(count);
s->ReadBuffer(buf.data(), count);
} // 離開作用域自動 delete fs → CloseHandle
ReadBuffer/WriteBuffer 內部無額外緩衝,應用層建議 64KB–256KB 塊讀寫。TFileStream 不支援 FILE_FLAG_OVERLAPPED;需高併發請直接用 THandleStream 包裝 CreateFile(..., FILE_FLAG_OVERLAPPED) + ReadFileEx/WriteFileEx。CreateFileMapping/MapViewOfFile,VCL 無內建封裝需自行實現。WriteComponent 適合元件樹持久化;純數據結構請用 TStream::WriteBuffer + 版本號 + CRC32 自定義協議。TFileStream fs("a.txt", fmOpenRead); 棧上構造 → 離開作用域析構 → CloseHandle 正確,但構造拋異常時檔案未開啟,析構不會執行,無洩漏風險,但調試時易誤以為檔案已關閉。fmOpenWrite | fmShareDenyNone,進程 B fmOpenRead | fmShareDenyWrite → B 開啟失敗 ERROR_SHARING_VIOLATION。THandleStream 構造後關閉原 HANDLE → 流操作全部失敗返回 0/拋異常。掌握 TFileStream 與 THandleStream 的分工邊界、模式位掩碼、RAII 封裝,你就能在 VCL 應用中構建健壯、高性能的文件 I/O 層。