1. 儲存位元據
SQLite提供的綁定二進位參數介面函數為:
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
我們希望使用的是一套經過封裝的COM介面,將上面這個函數封裝為COM介面的形式
BindParaByIndex( LONG index, VARIANT val);
使用VARIANT變數來傳遞位元據,可以使用到它的一個SAFEARRAY指標,它儲存了位元據的地址和位元據的位元組長度。
在我們的COM介面中可以這樣進行調用原始介面:
Sqlite3_bind_blob(m_pStmt, val.parray, val.parray->rsground->cElement,SQLITE_TRANSIENT);
構造一個例子測試我們的介面:
BYTE Data[] = {0x01,0x02,0x03,0x04,0x05};
CComSafeArray<byte> *pcsfa;
CComSafeArrayBound bound[1];
bound[0].SetCount(5);
bound[0].SetLowerBound(0);
pcsfa = new CComSafeArray<byte>(bound,1);
for(LONG i = 0; i <(LONG)5; i++)
{
HRESULT hr = pcsfa->SetAt(i,Data[i]);
}
_variant_t variant;
variant.vt = VT_ARRAY | VT_UI1;
variant.parray = pcsfa->m_psa;
將五個位元組的資料封裝到VARIANT變數中,然後調用相應的介面,將它們儲存到資料庫中,然後
調用下面的讀取二進位介面,將資料讀取出來,看是否讀取的資料和儲存的資料一致.
2. 讀取位元據
讀取二進位參數需要用到下面兩個SQLite提供的API:
const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
訪問也通過COM介面來實現:
GetBlobData(LONG index, VARIANT* pval);
如何將原始介面讀出來的資料封裝到VARIANT結構中去呢,網上這方面的參考資料好少,差了不少資料,發現網上有不上SAFEARRAY的實現方案,但是我一一試了一下沒有一個可以將位元讀入SAFEARRAY結構的,Mentor給我推薦了一個CcomSafeArray類,這個類成功實現了資料的儲存。
CComVariant cVal;
int nLen = sqlite3_column_bytes(m_pStmt,nIndex);
const void* pcvData = (const void*)sqlite3_column_blob(m_pStmt,nIndex);
BYTE* pData = new BYTE[nLen];
memcpy(pData,pcvData,nLen);
CComSafeArray<byte> *pcsfa;
CComSafeArrayBound bound[1];
bound[0].SetCount(nLen);
bound[0].SetLowerBound(0);
pcsfa = new CComSafeArray<byte>(bound,1);
for(LONG i = 0; i <(LONG)nLen; i++)
{
HRESULT hr = pcsfa->SetAt(i,pData[i]);
}
cVal = pcsfa->m_psa;
cVal.vt = VT_ARRAY | VT_UI1;
delete pData;
cVal.Detach(pVal);
OK,現在可以通過下面的代碼來測試是否成功讀取了所有的位元據。測試代碼如下:
_variant_t val;
val = GetBlobData(nIndex); //nIndex表示BLOB類型資料的索引值
byte buf[5];
if(val.vt == (VT_UI1|VT_ARRAY))
{
for(LONG index = 0; index < 5; index++)
{
::SafeArrayGetElement(val.parray,&index,buf+index);
}
}
for(int j = 0; j < 5; j++)
{
cout << “0x” << hex <<(int) buf[j]<<endl;//測試結果為0x01,0x02,0x03,0x04,0x05
}