师惠萍,程耀瑜,王诗琴,刘永林,雷红淼
(中北大学 山西省现代无损检测工程技术研究中心, 太原 030051)
在设计数据库的过程中,会经常要存储一些图形、长文本、多媒体等各种各样的程序文件,如果在数据库中仅存储这些文件的路径信息,虽然可以大大减小数据库的大小,但是由于文件存储在磁盘上,除了维护数据库外还要维护文件的路径信息,保持二者的一致,对于管理数据库非常不便,同时也给数据的安全带来隐患。如果把这些文件的内容作为一个记录的一个字段值直接保存到数据库中,这样不仅能够简化数据库和文件的管理工作,还能保证数据的安全[1-2]。本文以VC++6.0为开发工具,选取SQL Server 2000数据库存放图像数据,采用ADO方式连接数据库,介绍如何从数据库中存取图像数据并显示出来。
目前,图像的存取方法一般有两种:一种是间接存取法。这种方式是把图像存储在指定的文件夹下,把保存图像文件所在的路径和文件名保存在数据库中,它对图像的存取则是根据图像文件的存储路径和文件名来进行。这种方法对数据的管理不方便,对图像信息安全性和可靠性也不能保证,不适合保存重要的图像信息;第二种方法是直接存取法。它是把图像信息直接保存在数据库表中。这是目前图像数据库技术发展的主流,可以保证图像数据的一致性和安全性。但在读取技术实现上,很多数据库不支持图像数据的直接存取,必须由第三方开发的工具来完成数据库中图像数据的存取[3-5]。
图像可以看作是一种特殊的BLOB数据,BLOB(Binary Large Object)数据是指非常巨大的不定的二进制或者字符型数据。通常是文档(.txt、.doc)和图片(.jpeg、.gif、.bmp),可以存储在数据库中。在SQL Server 2000中,BLOB可以是text、ntext或是image数据类型。
ADO是应用级的编程接口,它以OLE DB为基础,对OLE DB进行了封装。ADO访问数据库是通过访问OLE DB数据并提供程序来进行的,提供了一种对OLE DB数据提供程序的简单高层访问接口。ADO封装了大量的COM接口,基于通用对象模型,不仅提供了多种语言的访问技术(VB,VC等),也可用脚本语言来访问(VbScript VcScript)[6]。
ADO提供了3个基本接口:
_ConnectionPtr接口返回一个记录集或一个空指针。通常使用它创建一个数据连接。
_CommandPtr接口返回一个记录集。它提供了一种简单的办法来执行返回记录集的存储过程和SQL语句。
_RecordsetPtr接口是一个记录集对象。它对记录集提供了更多的控制功能,如记录锁定,游标控制等。
在VC++中,使用ADO之前必须在工程的stdafx.h文件里添加对ADO的支持代码,即使用#import指令引人ADO动态链接库文件,使编译器能正确编译。代码如下:
#import "c:program filescommon filessystemadomsado 15 .d11"
no_namespace rename("EOF","adoEOF")
再初始化COM库,代码如下:
CoInitialize ( NULL );
用ADO访问数据库,首先要创建连接(Connection)对象建立与数据源的连接,然后创建记录集(Recordset)对象,实现对数据库的访问。
ADO的Field(域)对象为BLOB数据提供了AppendChunk和GetChunk两种方法。通过他们可以像读写文件一样,把其他文件的内容写入数据库,或把数据库的内容读出来再保存到文件中。在VC++中,AppenChunck把图像文件的数据写入数据库的image类型字段,GetChunck读出image字段数据,显示图像或保存为图片文件。
结合本文开发的“射线图像处理与图像数据库管理系统”说明应用程序中存取数据库图像的实现方法。系统的“图像存取及显示”模块可以实现图像遍历显示、图像入库[7-8]。
(1)在SQL Server 2000中建立一个数据库TXDB,新建表tbTX,表的字段设计如图1所示。
图1 表tbTX的字段设计
(2)在VC++中添加各控件并更改其属性,设计图像存取及显示模块窗口界面,如图2所示。
图2 窗口界面设计
(3)使用ADO对象:进入ADO动态库,初始化和释放COM库,新建UDL文件,设置数据库链接。具体步骤不做介绍。
(4)添加两个处理BLOB数据的自定义函数:
BOOL TXAppenChunk(FieldPtr pField, LPVOID lpData,UINT nBytes);
BOOL TXGetChunk(FieldPtr pField, LPVOID lpData);
其中,TXAppenChunk函数用来把数据写入数据库表的BLOB字段,其参数pField即为代表某BLOB字段类型的字段对象指针,lpData参数指向要写入的数据。
TXGetChunk函数用来读取BLOB字段的数据,其参数pField即为代表某BLOB字段类型的字段对象指针,lpData参数指定用来存放读取到BLOB数据的地址。
void CTXDlg::OnAddNew()
{ CFile file;
if (file.Open(m_strPathName, CFile::modeRead))
//打开文件
{ long length = (long) file.GetLength ();
//获取文件长度
BYTE *pbuf = new BYTE[length];
//为读文件建立缓存区
if (pbuf != NULL && file.Read(pbuf, length) = = (DWORD)length)
{ m_pRecordset->AddNew(); //添加记录
m_pRecordset->Fields->GetItem(long(1))->PutValue(_variant_t(dlg.GetFileName()));
//调用TXAppendChunk函数
TXAppendChunk(FieldPtr(m_pRecordset->GetFields()->GetItem(_bstr_t("Bmp"))),
pbuf, length);
m_pRecordset->Update();}}}
void CTXDlg :: ShowPic ()
//使用ShowPic函数来显示图像。
{ if(m_pRecordset==NULL)
return ;
_variant_t var;
CString strValue;
var=m_pRecordset->Fields->GetItem(_bstr_t("Name"))->GetValue();
if(var.vt != VT_NULL)
strValue = (LPCSTR)_bstr_t(var);
点的中心度是节点中心性的判断指标之一,是衡量节点与其他节点联系广度的重要参数,若一个节点同较多节点相连则该节点中心度较高。分析表明点的中心度较高的前几位关键词依次为正念训练、心理健康、正念、正念干预、社会生活问题、MBSR,这由图谱中节点面积大小可得到验证。
m_strName=strValue;
UpdateData (FALSE);
//获得图片数据,显示图片
long size = m_pRecordset->Fields->GetItem(_bstr_t("Bmp"))->ActualSize;
if ( size > 0)
{ BYTE *lpData = new BYTE[size];
//调用TXGetChunk函数,把图像数据读入到lpData
if (TXGetChunk(m_pRecordset->GetFields()->GetItem("Bmp"), (LPVOID)lpData))
CPicture m_Pic;
m_Pic.LoadPictureData(lpData,size);
CClientDC dc(this);
m_Pic.UpdateSizeOnDC(&dc);
m_Pic.Show(&dc, CRect(150,70,150+250,70+250) );}
delete[]lpData;
lpData = NULL;}
else if(size= =0) MessageBox("该记录为空!");}
本文采用直接将图像数据存储在数据库关系表中的方法,消除了将图像数据作为文件存放的种种弊端,提高图像数据的可用性和安全性。结合实例实现了图像存取,遍历查看的功能。图像的格式不仅支持BMP格式,还支持其他格式的图像,如jpg等。程序运行结果如图3所示。
图3 程序运行结果
[1]原奕.Visual C++实践与提高—数据库开发与工程应用[M].北京:中国铁道出版社,2006:277-278.
[2]求是科技.Visual C++数据库通用模块及典型系统开发实例导航[M].北京:人民邮电出版社,2006:100-105.[3]王姝.数据库图像字段数据存储与读取技术应用研究[J].科学技术与工程,2010,10(3):682-685.
[4]杨宁,申强,谢静.SQL Server数据库中图像存取技术研究[J].南京晓庄学院学报,2010,5(3):82-84.
[5]刘显荣.用VC++实现数据库中图片的存取与显示[J].计算机应用研究,2006(5):163-165.
[6]王樱,徐雨明.VC++中数据库访问技术研究[J].微计算机信息,2006,22(4-3):256-258.
[7]郑阿奇.Visual C++教程[M].北京:清华大学出版社,2005:246-248.
[8]高金兰.数据库原理与SQL Server应用[M].武汉:武汉大学出版社,2008:103.