您的位置:首页 > 数据库

关于将类对象数据存入到数据库中的实现方法

2011-01-25 17:45 766 查看
问题背景:因为在做图像比较这方面的事情,需要将图像的特征保存到ACCESS数据库中去。图像的特征包括基于块的16*8的double型数组和全局的8维double型数组,希望将数组保存到数据库中。之前有从网上找到将图像数据从数据库中存取的代码,如下所示:

取图像:

void CProTestDlg::getImgFromDB(_RecordsetPtr pRecord, IplImage** pImg)
{
try{
long nSize = pRecord->GetFields()->GetItem("image")->ActualSize;
if(nSize > 0)
{
_variant_t    varBLOB;
varBLOB = pRecord->GetFields()->GetItem("image")->GetChunk(nSize);
if(varBLOB.vt == (VT_ARRAY | VT_UI1))
{
if(BYTE *pBuffer = new BYTE [nSize+1])         ///重新申请必要的存储空间
{
char *pBuf = NULL;
SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
memcpy(pBuffer,pBuf,nSize);               ///复制数据到缓冲区m_pBMPBuffer
SafeArrayUnaccessData (varBLOB.parray);
delete [] pBuffer;
pBuf=0;
}
//输出文件
_variant_t varChunk;
BYTE *pBuf = NULL;
pBuf = (BYTE*)GlobalAlloc(GMEM_FIXED,nSize);
SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
CFile outFile("2.bmp",CFile::modeCreate|CFile::modeWrite);
LPSTR buffer = (LPSTR)GlobalLock((HGLOBAL)pBuf);
outFile.Write(buffer,nSize);
GlobalUnlock((HGLOBAL)pBuf);
outFile.Close();
SafeArrayUnaccessData (varBLOB.parray);
}
if(*pImg)
cvZero(*pImg);
*pImg=cvLoadImage("2.bmp");

CFile::Remove("2.bmp" );
}
}catch(_com_error e){
CString errormessage;
errormessage.Format("图片显示失败!/r/n错误信息:%s",e.ErrorMessage());
AfxMessageBox(errormessage);
}
}


存图像:

void CProTestDlg::putImg2DB(_RecordsetPtr pRecord, int num, CString* dscptn, IplImage* Img)
{
try{
pRecord->AddNew();
pRecord->PutCollect("type", _variant_t(num));
if(dscptn != NULL)
pRecord->PutCollect("discription", _variant_t(*dscptn));

if(Img){

cvSaveImage("1.bmp",Img);

CFile f;

// TODO: Add your control notification handler code here

CString  FilePathName("1.bmp");

CFileException e;

if(f.Open(FilePathName, CFile::modeRead | CFile::typeBinary, &e))

{

int nSize = f.GetLength();          //先得到文件长度

BYTE * pBuffer = new BYTE [nSize];  //按文件的大小在堆上申请一块内存

if (f.Read(pBuffer, nSize) > 0 )    //把文件读到pBuffer(堆上申请一块内存)
{

BYTE *pBuf = pBuffer;     ///下面这一大段是把pBuffer里的数据放到库中
VARIANT            varBLOB;
SAFEARRAY     *psa;
SAFEARRAYBOUND     rgsabound[1];

if(pBuf)
{
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = nSize;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
for (long i = 0; i < (long)nSize; i++)
SafeArrayPutElement (psa, &i, pBuf++);

varBLOB.vt = VT_ARRAY | VT_UI1;
varBLOB.parray = psa;
pRecord->GetFields()->GetItem("image")->AppendChunk(varBLOB);
}
delete [] pBuffer;     //删掉堆上申请的那一块内存
pBuf=0;                //以防二次乱用
}
f.Close();                //这里一定要记得先关闭文件,后面再Remove,否则会出现共享冲突
CFile::Remove("1.bmp");
}
pRecord->Update();
}
}catch(_com_error *e){
AfxMessageBox(e->ErrorMessage());
}
}


利用ADO中的OLE大型二进制域来保存复杂的数据结构,因此想到采用类似的方法把特征对象也这样的处理。如何将数据二进制化?显然,可以把类对象先进行序列化进文件中,再通过二进制方式打开文件进行转化。

序列化的方法,对象类必须继承MFC中的CObject类,并且要重载拷贝构造函数(不然可能会出现CObject类中private成员的问题)和Serialize方法。

具体代码如下,CFeature类封装了两个数组:

存数据:

void CProTestDlg::saveFeature2DB(_RecordsetPtr pRecord,  CFeature feature)
{
CFile fileStore(_T("feature.dat"), CFile::modeWrite | CFile::modeCreate);
CArchive arStore(&fileStore, CArchive::store);
feature.Serialize(arStore);
arStore.Flush();
arStore.Close();
fileStore.Close();

try{
CFile f;
CString  FilePathName("feature.dat");

CFileException e;

if(f.Open(FilePathName, CFile::modeRead | CFile::typeBinary, &e))
{
int nSize = f.GetLength();          //先得到文件长度
BYTE * pBuffer = new BYTE [nSize];  //按文件的大小在堆上申请一块内存

if (f.Read(pBuffer, nSize) > 0 )    //把文件读到pBuffer(堆上申请一块内存)
{
BYTE *pBuf = pBuffer;     ///下面这一大段是把pBuffer里的数据放到库中
VARIANT            varBLOB;
SAFEARRAY     *psa;
SAFEARRAYBOUND     rgsabound[1];

if(pBuf)
{
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = nSize;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
for (long i = 0; i < (long)nSize; i++)
SafeArrayPutElement (psa, &i, pBuf++);

varBLOB.vt = VT_ARRAY | VT_UI1;
varBLOB.parray = psa;
pRecord->GetFields()->GetItem("feature")->AppendChunk(varBLOB);
}
delete [] pBuffer;     //删掉堆上申请的那一块内存
pBuf=0;                //以防二次乱用
}
f.Close();                //这里一定要记得先关闭文件,后面再Remove,否则会出现共享冲突
CFile::Remove(FilePathName);
}
pRecord->Update();
}catch(_com_error *e){
AfxMessageBox(e->ErrorMessage());
}

}


取数组:

void CProTestDlg::getFeatureFromDB(_RecordsetPtr pRecord, CFeature &feature)
{
try{
long nSize = pRecord->GetFields()->GetItem("feature")->ActualSize;
if(nSize > 0)
{
_variant_t varBLOB;
varBLOB = pRecord->GetFields()->GetItem("feature")->GetChunk(nSize);
if(varBLOB.vt == (VT_ARRAY | VT_UI1))
{
if(BYTE *pBuffer = new BYTE [nSize+1])         ///重新申请必要的存储空间
{
char *pBuf = NULL;
SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
memcpy(pBuffer,pBuf,nSize);               ///复制数据到缓冲区m_pBMPBuffer
SafeArrayUnaccessData (varBLOB.parray);
delete [] pBuffer;
pBuf=0;
}
//输出文件
_variant_t varChunk;
BYTE *pBuf = NULL;
pBuf = (BYTE*)GlobalAlloc(GMEM_FIXED,nSize);
SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
CFile outFile("feature.dat",CFile::modeCreate|CFile::modeWrite);
LPSTR buffer = (LPSTR)GlobalLock((HGLOBAL)pBuf);
outFile.Write(buffer,nSize);
GlobalUnlock((HGLOBAL)pBuf);
outFile.Close();
SafeArrayUnaccessData (varBLOB.parray);
}

CFile fileLoad(_T("feature.dat"), CFile::modeRead);
CArchive arLoad(&fileLoad, CArchive::load);
feature.Serialize(arLoad);
arLoad.Flush();
arLoad.Close();
fileLoad.Close();
CFile::Remove("feature.dat" );
}
}catch(_com_error e){
CString errormessage;
errormessage.Format("特征提取失败!/r/n错误信息:%s",e.ErrorMessage());
AfxMessageBox(errormessage);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息