关于将类对象数据存入到数据库中的实现方法
2011-01-25 17:45
766 查看
问题背景:因为在做图像比较这方面的事情,需要将图像的特征保存到ACCESS数据库中去。图像的特征包括基于块的16*8的double型数组和全局的8维double型数组,希望将数组保存到数据库中。之前有从网上找到将图像数据从数据库中存取的代码,如下所示:
取图像:
存图像:
利用ADO中的OLE大型二进制域来保存复杂的数据结构,因此想到采用类似的方法把特征对象也这样的处理。如何将数据二进制化?显然,可以把类对象先进行序列化进文件中,再通过二进制方式打开文件进行转化。
序列化的方法,对象类必须继承MFC中的CObject类,并且要重载拷贝构造函数(不然可能会出现CObject类中private成员的问题)和Serialize方法。
具体代码如下,CFeature类封装了两个数组:
存数据:
取数组:
取图像:
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); } }
相关文章推荐
- 保存数据库中其他对象不变,删除数据库中所有数据的实现方法
- 保存中其他对象不变,删除数据库中所有数据的实现方法
- 保存数据库中其他对象不变,删除数据库中所有数据的实现方法
- Python基于多线程实现抓取数据存入数据库的方法
- 关于数据库中去掉数据空格的方法!!!
- 关于Echarts中formatter实现动态数据的方法
- 关于用VC,VB进行图像数据(二进制大对象)存储数据库的一点心
- Java实现数据批量导入数据库(优化速度-2种方法)
- 关于对数据库统计每个时间段内的数据的实现方式
- 关于C#数据库删除数据时提示未将对象引用设置到对象的实例
- php获取数据库中数据的实现方法
- CI框架入门示例之数据库取数据完整实现方法
- 报错:对象必须实现 IConvertible;以分隔符进行分割链接concat_ws的使用方法;mysql数据类型转换cast,convert
- CI框架入门示例之数据库取数据完整实现方法
- Java实现从数据库导出大量数据记录并保存到文件的方法
- 将对象存为数据库二进制数据的处理方法
- [DNN学习所得]CBO——简化从数据库读取数据并实例化对象的有效方法
- jsp从数据库获取数据填充下拉框实现二级联动菜单的方法
- 11g数据导入10g数据库方法实现
- 往TreeSet中存入自定义对象,并且使用自定义排序方法(实现comparetor)