代码如下,前一段为存,后一段为取,存正常,取出错.
另外,还有几个顺带的问题,1.AppendChunk,GetChunk是不是对所操作的字段的类型有要求,必须是text或image类型?我本来是想用这两方法来对所有类型进行操作的, 试了下,好象别的类型不行.2.另外,C++中类的公共成员,保护成员,私有成员命名时,前缀是什么,这个好象在哪里看过,忘了,也不知道是哪门语言上的,知道的也顺便说下
3.我在用ADO操作的时候,以前用catch(_com_err e)这样捕捉,好象连一般的打开记录集Open出错时,都不会抛出,于是后来就一直用catch(...),不过,现在不知道怎么把错误码或详细信息读出来,在catch中用GetLastError好象不行,知道怎么用的也说下,谢谢 try
{
lstate = m_pRecordset->State;
if(lstate == adStateOpen)
m_pRecordset->Close();
m_pRecordset->Open((_bstr_t)szCommand,
m_pConnection.GetInterfacePtr(),
adOpenDynamic,
adLockOptimistic,
adCmdText); Fields *pFields = m_pRecordset->GetFields();
Field *pField = pFields->GetItem("other3");
CFile imagefile;
if(0 == imagefile.Open("C:\\WINNT\\Blue Lace 16.bmp",CFile::modeRead))
return;
long nLength = imagefile.GetLength();
BYTE *pbuf = NULL;
BYTE *pBufEx = NULL;
//存
pbuf = new BYTE[nLength];
pBufEx = pbuf;
if(pbuf == NULL)
return; //allocate memory error;
imagefile.Read(pbuf,nLength); //read the file into memory //build a SAFFERRAY
SAFEARRAY* psa;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = nLength;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound); for (long j = 0; j < nLength; j++)
SafeArrayPutElement (psa, &j, pBufEx++);
VARIANT varBLOB;
varBLOB.vt = VT_ARRAY | VT_UI1;
varBLOB.parray = psa;
pField->AppendChunk(varBLOB);
delete []pbuf;//取 VARIANT varBLOB2;
pField->get_ActualSize(&nLenth); //这里取出来的长度和上面存入的长度一致
varBLOB2 = pField->GetChunk(nLenth); //运行到这句的时候,异常抛出.
if(varBLOB2.vt == (VT_ARRAY | VT_UI1))
{
pbuf = (BYTE*)GlobalAlloc(GMEM_FIXED,nLenth);
SafeArrayAccessData(varBLOB2.parray,(void **)pbuf); //Build a File in Windows Temp Directory
char tmpPath[_MAX_PATH+1];
GetTempPath(_MAX_PATH,tmpPath);
CString strFileName = "temp.bmp";
strFileName = tmpPath+strFileName;
CFile outFile(strFileName,CFile::modeCreate|CFile::modeWrite);
LPSTR buffer = (LPSTR)GlobalLock((HGLOBAL)pbuf);
outFile.WriteHuge(buffer,nLenth);
GlobalUnlock((HGLOBAL)pbuf);
outFile.Close();
SafeArrayUnaccessData (varBLOB2.parray);
} }
catch(...)
{
AfxMessageBox("E");
}
另外,还有几个顺带的问题,1.AppendChunk,GetChunk是不是对所操作的字段的类型有要求,必须是text或image类型?我本来是想用这两方法来对所有类型进行操作的, 试了下,好象别的类型不行.2.另外,C++中类的公共成员,保护成员,私有成员命名时,前缀是什么,这个好象在哪里看过,忘了,也不知道是哪门语言上的,知道的也顺便说下
3.我在用ADO操作的时候,以前用catch(_com_err e)这样捕捉,好象连一般的打开记录集Open出错时,都不会抛出,于是后来就一直用catch(...),不过,现在不知道怎么把错误码或详细信息读出来,在catch中用GetLastError好象不行,知道怎么用的也说下,谢谢 try
{
lstate = m_pRecordset->State;
if(lstate == adStateOpen)
m_pRecordset->Close();
m_pRecordset->Open((_bstr_t)szCommand,
m_pConnection.GetInterfacePtr(),
adOpenDynamic,
adLockOptimistic,
adCmdText); Fields *pFields = m_pRecordset->GetFields();
Field *pField = pFields->GetItem("other3");
CFile imagefile;
if(0 == imagefile.Open("C:\\WINNT\\Blue Lace 16.bmp",CFile::modeRead))
return;
long nLength = imagefile.GetLength();
BYTE *pbuf = NULL;
BYTE *pBufEx = NULL;
//存
pbuf = new BYTE[nLength];
pBufEx = pbuf;
if(pbuf == NULL)
return; //allocate memory error;
imagefile.Read(pbuf,nLength); //read the file into memory //build a SAFFERRAY
SAFEARRAY* psa;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = nLength;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound); for (long j = 0; j < nLength; j++)
SafeArrayPutElement (psa, &j, pBufEx++);
VARIANT varBLOB;
varBLOB.vt = VT_ARRAY | VT_UI1;
varBLOB.parray = psa;
pField->AppendChunk(varBLOB);
delete []pbuf;//取 VARIANT varBLOB2;
pField->get_ActualSize(&nLenth); //这里取出来的长度和上面存入的长度一致
varBLOB2 = pField->GetChunk(nLenth); //运行到这句的时候,异常抛出.
if(varBLOB2.vt == (VT_ARRAY | VT_UI1))
{
pbuf = (BYTE*)GlobalAlloc(GMEM_FIXED,nLenth);
SafeArrayAccessData(varBLOB2.parray,(void **)pbuf); //Build a File in Windows Temp Directory
char tmpPath[_MAX_PATH+1];
GetTempPath(_MAX_PATH,tmpPath);
CString strFileName = "temp.bmp";
strFileName = tmpPath+strFileName;
CFile outFile(strFileName,CFile::modeCreate|CFile::modeWrite);
LPSTR buffer = (LPSTR)GlobalLock((HGLOBAL)pbuf);
outFile.WriteHuge(buffer,nLenth);
GlobalUnlock((HGLOBAL)pbuf);
outFile.Close();
SafeArrayUnaccessData (varBLOB2.parray);
} }
catch(...)
{
AfxMessageBox("E");
}
pField->get_ActualSize(&nLenth);
varBLOB2 = pField->GetChunk(nLenth);
建议使用_variant_t,不要直接使用VARIANT
以下是我自己的测试代码,是可用的
_variant_t varBLOB;
varBLOB = pRs->GetFields()->GetItem("img")->GetChunk(lDataSize);
if(varBLOB.vt == (VT_ARRAY | VT_UI1))///判断数据类型是否正确
{
char *pBuf = NULL;
SafeArrayAccessData(varBLOB.parray,(void **)&pBuf2);
///得到指向数据的指针
/*****在这里我们可以对pBuf中的数据进行处理*****/ HANDLE hFile= CreateFile(
_T("c:\\tx2.jpg"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ ,
NULL,
CREATE_NEW | OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
); DWORD writtedSize=0;
WriteFile(hFile,pBuf2,lDataSize,&writtedSize,NULL);
CloseHandle(hFile);
SafeArrayUnaccessData(varBLOB.parray);
}
少说了一句,要用long
这一句比较可疑,因为pbuf是从安全数组对象里取得的一个指向内存块的指针,而HGLOBAL是一个由GlobalAlloc得到的标识一个全局内存块句柄,应该不能直接转换,除非pbuf是这样得来的
pbuf = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);但显然不是的另外呢outFile.WriteHuge(buffer,nLenth);这个方法已经不常用了,已经被Write所替代。LPSTR buffer = (LPSTR)GlobalLock((HGLOBAL)pbuf);这个强制转换很可疑,因为对于HGLOBAL指向的内存结构实际上应该是一个结构体,包含了一个计数器,依靠增减这个引用计数器来保护这个内存块,感觉有些问题虽然不知道你为什么使用GlobalLock这一族的API,可能是因为有多进程或者多线程需要访问同一块内存但是你读取数据库BLOB字段,用这种方式好像并不是很好。