用VC++存取图片到数据库的解决办法,解决必有分! 用VC++存取图片到数据库的解决办法,解决必有分!只要给我提示就可以了。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 在用Visual C++编写应用程序时,常会遇到如何存取数据库中大对象的问题。大对象文档以二进制数据形式保存在BLOB类型的字段中,这些大对象可能是Word、Execl或"图片文件"等,目前多数数据库都支持BLOB类型的字段。 VC存取这些大对象数据有众多方法,如OLE、ActiveX等,事实上VC的MFC提供了一个很方便的实现方法,即利用MFC提供的CLongBinary类可以方便地实现存取BLOB字段。下面笔者将举例说明。 首先用以下SQL语句建一个含BLOB字段的数据表: CREATE TABLE REPORTTABLE(REGISTERNUM CHAR(12) NOT NULL,REPORT BLOB(5M),PRIMARY KEY(REGISTERNUM)); 建完该表后,配置好ODBC数据源,设定数据源名为ABCDB。 我们用VC的MFC AppWizard建一个新的Project,设定项目名为ABC,下一步选Single Document,在提示你想包含什么样的数据库支持时,选Header files only,然后完成建立。 接着在Resources的Dailog资源中新建一个FormView,打开该FormView,启用ClassWizard,建立一个新类,设定类名叫CReportRecordSet,Base Class选CRecordSet,然后选ABCDB为数据源,再选择表REPORTTABLE,启动ClassWizrd,并建立新类CReportFormView,Base Class为CRecordView,选Recordset时,选CReportRecordSet。 打开ReportRecordSet.h,找到该行:CString m_REPORT; 改为CLongBinary m_REPORT;这样程序就知道m_REPORT是和BLOB字段交换数据。同样,我们还需要修改另外几处,打开ReportRecordSet.cpp后,删除m_REPORT = _T("");一句。再找到RFX_Text(pFX, _T("[REPORT]"), m_REPORT);一句,将其改为RFX_LongBinary(pFX, _T("[REPORT]"), m_REPORT); ODBC方法存取数据库时使用RFX_LongBinary;DAO方法则用DFX_LongBinary。 再次打开FormView,添加一个Edit控件,并用ClassWizard将它和member variable m_pSet-〉m_ REGISTERNUM关联,然后在FormView上增加三个按键,Caption名分别叫“取得Word文档”、“更新word文档”、“新增word文档”。并分别为这三个按键建立各自的Function,然后我们为这三个按键增加相应的代码。在按键“取得Word文档”的Function中加入如下代码: try //该程序的所在当前目录是e:\qc\abc\ { if (m_pSet-〉IsEOF()) AfxMessageBox("没有该小组的成果报告"); else {//下面检测临时文件tyj.doc是否存在 HANDLE hFind; WIN32_FIND_DATA findData = {0}; hFind=FindFirstFile("e:\\qc\\abc\\tyj.doc",&&findData); // FindFirstFile是Windows API 函数 if(hFind = = INVALID_HANDLE_VALUE) AfxMessageBox("不存在临时文件"); else {AfxMessageBox("有临时文件"); DeleteFile("e:\\qc\\abc\\tyj.doc"); //利用API函数删除该临时文件 } CString strFileName="e:\\qc\\abc\\tyj.doc"; CFile outFile(strFileName,CFile::modeCreate|CFile::modeWrite); //modeCreate指示构造函数创建一个新文件 //下面这段把已经在内存中的BLOB字段数据内容写到临时生成的文件tyj.doc中 LPSTR buffer = (LPSTR)GlobalLock(m_pSet-〉m_REPORT.m_hData); outFile.WriteHuge(buffer,m_pSet-〉m_REPORT.m_dwDataLength); GlobalUnlock(m_pSet-〉m_REPORT.m_hData); outFile.Close(); ShellExecute(NULL,NULL,_T("tyj.doc"),NULL,_T("e:\\qc\\abc\\"),NULL); //下面执行外部程序,Word会自动启动并打开tyj.doc} } catch(CExceptionpE) { pE-〉ReportError(); pE-〉Delete(); return; } 在按键“更新word文档”的Function中加入以下程序代码: m_pSet-〉Edit(); // 声明编辑当前记录 UpdateData(TRUE); CFile fileword; CFileStatus fileStatus; CString fileLocate; static char BASED_CODE szFilter[] = "WORD Files (.doc)|.doc||"; // 下面将弹出典型的打开文件对话框,您可以选择任何目录下的.doc文件 CFileDialog dlg(TRUE,NULL,NULL,0,szFilter,this); if(dlg.DoModal()= =IDOK) fileLocate=dlg.GetPathName(); else fileLocate=""; if(fileLocate= ="") AfxMessageBox("您没选文件"); else{ fileword.Open(fileLocate,CFile::modeRead); fileword.GetStatus(fileStatus); m_pSet-〉m_REPORT.m_dwDataLength=fileStatus.m_size; HGLOBAL hGlobal = GlobalAlloc(GPTR,fileStatus.m_size); m_pSet-〉m_REPORT.m_hData = GlobalLock(hGlobal); fileword.ReadHuge(m_pSet-〉m_REPORT.m_hData,fileStatus.m_size); //把您选择的文件的数据写入m_pSet-〉m_REPORT m_pSet-〉SetFieldDirty(&&m_pSet-〉m_REPORT); m_pSet-〉SetFieldNull(&&m_pSet-〉m_REPORT,FALSE); m_pSet-〉Update(); // 更新记录 GlobalUnlock(hGlobal); } 上述代码只要稍做修改,即可把Execl等各类文件存入数据库中。对应按键“新增word文档”只需要复制“更新Word文档”中的代码,并把m_pSet-〉Edit();换成m_pSet-〉AddNew();即可。完成上述步骤后,打开abc.cpp,把RUNTIME_CLASS(CAbcView));这句换成RUNTIME_CLASS(CReportFormView)); 这样程序启动时就显示了该FormView。 以上所有代码均在IBM UDB6、Visual C++ 6.0、Windows 98环境下编译通过。 to 楼主,拿来主义可要不得, cnshinhwa(月夜森林) 的方法稍加修改就可以应用到图片的存取,你怎么不自己动脑筋呢 其实大家没有明白我的意思吧我的意思是从数据库中直接显示各种文件,而不是根据文件类型从数据库中再保存到文件再显示,而是直接显示,其实cnshinhwa(月夜森林)的说明我已经能够完成各种文件的存取但是与我的初衷有本质的区别的。 但是我还是应该谢谢cnshinhwa(月夜森林)我会给他加分的。 如果你使用ADO的话,使用AppendChunk()存储,使用GetChunk()读取。例子: 记得大概是如此: LPVOID m_pJPGData; //jpg 通过FieldPtr,函数GetActualSize()得到字段的字节数, 分配此字节内存, GetChunk("jpg",m_pJPGData); //jpg是数据库中的字段。 查查MSDN和ADO帮助文件,很简单的问题。 mfkzj() 我没有收到文件,请再试一次[email protected] 实际上就是BLOB字段的读写,www.vckbase.com的vc知识库第十期有一篇文章讲述了这个,带实例代码,去找一下吧。 其实, 先把文件写入数据库,用时从数据库读出写成临时文件,再按常规方法显示临时文件,之后删除临时文件。 这个方法是最简单,最可靠的了。我也明白你的意思,你是嫌这个麻烦,想把从数据库里读出的数据直接就显示出来。但是你错了,要实现你这种想法,你得跟踪分析windows运用handle的手段,把图片handle指向的数据写进数据库又读出来,这样就能直接用了。可是这样做已经比先前那个方法麻烦了,就算你做成功,极容易出现兼容性等问题,如果你把兼容性等问题都考虑全了,那等于你把windows图形API重新做出来了。假如你不愿意写临时文件是因为想节省硬盘,那么你也错了。一个临时文件被创建,立刻又读出来,马上就删掉,这些操作不到1秒就完成,由于硬盘缓存的机制,根本没有数据真正被写到硬盘上。 我已经收到mfkzj()的信,谢谢剩下的问题就有我自己来解决吧谢谢大家。 cnshinhwa月夜森林 你好: 我是一名大四学生,要做毕业设计。设计一个网络管理系统。其中我想将图标,图片等资源放入数据库。但苦于找不到相关技术文章。幸好今天在论坛看到你的帖子有介绍。你能把从数据库读取文件的源程序给我发一份吗..谢谢! MFC下WMI的使用 现在大家做GIS应用开发,都是使用什么组件呢? CListCtrl双击响应 关于单击和双击的问题 急! vmware虚拟机和主机通信问题(可以ping通) 问一个关于用GDI做游戏出现的问题 mfc写的OCX控件,怎么才能在事件里传递字符串? 静态类如何写? 关闭线程问题 高分赠送:《DirectX从入门到精通》的配套光盘中directsound的例子,mail:[email protected],谢谢! 继续提问:DLL中的难题!(导出类与消息映射) 能不能用CWebBrowser控件显示大的图像!如何实现!?实在非常着急的!多谢!50分!
我的意思是从数据库中直接显示各种文件,而不是根据文件类型从数据库中再保存到文件
再显示,而是直接显示,其实cnshinhwa(月夜森林)的说明我已经能够完成各种文件的存取
但是与我的初衷有本质的区别的。
例子:
记得大概是如此:
LPVOID m_pJPGData; //jpg
通过FieldPtr,函数GetActualSize()得到字段的字节数,
分配此字节内存,
GetChunk("jpg",m_pJPGData); //jpg是数据库中的字段。 查查MSDN和ADO帮助文件,很简单的问题。
www.vckbase.com的vc知识库第十期有一篇文章讲述了这个,带实例代码,去找一下吧。
这个方法是最简单,最可靠的了。
我也明白你的意思,你是嫌这个麻烦,想把从数据库里读出的数据直接就显示出来。
但是你错了,
要实现你这种想法,你得跟踪分析windows运用handle的手段,把图片handle指向的数据写进数据库又读出来,这样就能直接用了。
可是这样做已经比先前那个方法麻烦了,就算你做成功,极容易出现兼容性等问题,如果你把兼容性等问题都考虑全了,那等于你把windows图形API重新做出来了。假如你不愿意写临时文件是因为想节省硬盘,那么你也错了。
一个临时文件被创建,立刻又读出来,马上就删掉,这些操作不到1秒就完成,由于硬盘缓存的机制,根本没有数据真正被写到硬盘上。
剩下的问题就有我自己来解决吧
谢谢大家。
你好:
我是一名大四学生,要做毕业设计。设计一个网络管理系统。其中我想将图标,图片等资源放入数据库。但苦于找不到相关技术文章。幸好今天在论坛看到你的帖子有介绍。你能把从数据库
读取文件的源程序给我发一份吗..谢谢!