實際專案常需儲存圖片、音訊、文件等二進位資料。ADO 中 AppendChunk/GetChunk 配合 SAFEARRAY 是標準作法。本文給出完整儲存/讀取流程與示例工程下載。
CREATE TABLE [dbo].[userphoto] (
[id] [int] IDENTITY(1,1) NOT NULL,
[username] [varchar](50) NULL,
[old] [int] NULL,
[photo] [image] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
建立欄位 photo 類型為「OLE 物件」。示例工程已內建 Access 2000 資料庫。
// 假設 m_pBMPBuffer 指向長度 m_nFileLen 的二進位資料,Recordset 已開啟
char* pBuf = m_pBMPBuffer;
VARIANT varBLOB;
SAFEARRAY* psa;
SAFEARRAYBOUND rgsabound[1];
m_pRecordset->AddNew();
m_pRecordset->PutCollect("username", _variant_t("小李"));
m_pRecordset->PutCollect("old", _variant_t((long)28));
if (pBuf) {
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = m_nFileLen;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound); // 建立 BYTE 陣列
for (long i = 0; i < (long)m_nFileLen; i++)
SafeArrayPutElement(psa, &i, pBuf++); // 複製資料
varBLOB.vt = VT_ARRAY | VT_UI1;
varBLOB.parray = psa;
m_pRecordset->GetFields()->GetItem("photo")->AppendChunk(varBLOB);
}
m_pRecordset->Update(); // 寫入資料庫
long lDataSize = m_pRecordset->GetFields()->GetItem("photo")->ActualSize;
if (lDataSize > 0) {
_variant_t varBLOB = m_pRecordset->GetFields()->GetItem("photo")->GetChunk(lDataSize);
if (varBLOB.vt == (VT_ARRAY | VT_UI1)) {
char* pBuf = NULL;
SafeArrayAccessData(varBLOB.parray, (void**)&pBuf); // 取得資料指標
// 在此處理 pBuf 指向的二進位資料(如建立 CBitmap 顯示)
SafeArrayUnaccessData(varBLOB.parray);
}
}
感謝網友對上篇的指正與鼓勵。BLOB 處理關鍵在於 VARIANT 封裝 SAFEARRAY,掌握此模式即可應對各類二進位資料儲存需求。