1 导言
在许多项目开发中,因为存在着很多的数据需求存储,一般选用数据库来存储这些数据,使得数据库技能被越来越广泛地运用。在这些数据中有简略的文本文件,只需经过api的简略编程即可完成,但也存在许多大目标数据,比方图画、音频和视频等,其存储方式有所不同。作为大目标数据的图画数据,一般以blob(二进制大目标,binary large object)方式存储,例如access数据库中ole目标数据类型、sql server数据库中的image数据类型等。在vc++ 7.0的环境下,为了高效快捷的拜访图画数据,需求选用适宜的数据库拜访技能。
在vc++中规范的拜访数据库技能有很多种,依据开发的项目,笔者选用了数据库技能中最常见有用的两种技能ado技能和mfc odbc在access数据库中拜访图画数据。
2 图画数据拜访原理
尽管图画数据的格局有多种,例如bmp、jpg和gif等格局,但都能够看成是二进制流,即blob类型。blob类型数据需求占用较大的硬盘空间和内存,对存储功率和查询速度都有很大的影响。
图画数据的拜访分存储和读取两个进程。在存储进程中,因为寄存图画数据的字段是可变长度(长度一般为0~2g)的blob类型,无法直接存储,有必要首先将存储在文件中的图画数据以二进制流的方式读到缓冲区中,然后再将缓冲区中的图画数据添加到access数据库中的ole目标中。在读取进程中,将寄存在access数据库中的图画数据读到缓冲区中,然后在显现在用户界面上。图画数据的拜访原理如图1所示。
图1 图画数据拜访原理图
3 运用ado拜访图画数据
3.1 ado的介绍
ado(activex data objects)是microsoft数据库运用程序开发的接口,是建立在ole db技能之上的高层数据库访技能,简化了编程,且有利于程序的可移植性及可扩充性。
ado包含connection目标、command目标、parameter目标、recordset目标、field目标、error目标、property目标以及相应的调集目标,这些目标被封装在_connection -ptr接口、_commndptr接口和_recordsetptr接口这三个根本接口中。
3.2 ado衔接数据库
(1) 导入ado库
运用ado前需求在stdafx.h头文件中导入该库,只需运用import指令将此动态链接库导入,详细代码如下[1]:
#import“c:program filescommon files
systemadomsado15.dll”o_namespaceename(“eof”,
“adoeof”)
(2) 初始化com库
ado自身是一个com组件,在运用时需求初始化com库,需求调用coinitialize函数来完成。
:: coinitialize(null);
(3) 创立connection目标并衔接数据库
创立connection目标:
_connectionptr m_pconnection;
m_pconnection.createinstanc -e(“adodb.connection”);
衔接数据库:
_pconnection-》open(“provide -r=microsoft.jet.oledb.4.0;data
source = picture.mdb”, “”,“”, admodeunknown);
(4) 履行操作
m_precordset.createinstance(“adodb.recordset”);
m_precordset-》open
((_variant_t)strsql,_variant_t((idispatch*)
theapp.m_pconnection,true),adopendynamic,adlockoptimistic,adcmdtext);
3.3 图画数据的存储
关于一般数据,能够经过recordset目标的getcollect()和putcollect()函数来对数据进行存储和读取,而关于图画数据,就需求运用field目标中的appendchunk函数来进行存储和getchunk函数来进行读取。图画数据的存储进程能够分为以下三步:
(1) 翻开图画数据,取得数据长度;请求缓冲区,把文件读入此缓冲区。
(2) 结构一个一维数组,把缓冲区中的数据拷贝到数组中,然后结构一个变体目标,用数组来对此目标赋值。
(3) 调用appendchunk函数,把数据存入recordset目标的本地缓冲区。
详细完成代码如下:
if(m_pic.m_ipicture != null) m_pic.freepicturedata();
if(f.open(m_strphotopath, cfile::moderead |
cfile::typebinary, &e)) //翻开了一个图画文件
{nsize = f.getlength();//先得到图画数据长度
byte * pbuffer = new byte [nsize];
//依据数据的长度请求缓冲区
if (f.read(pbuffer, nsize) 》 0 )
//把图画数据读到缓冲区
{byte *pbuf = pbuffer;
//把pbuffer里的jpg数据放到库中
variant varblob;
safearray *psa;
safearraybound rgsabound[1];
//创立safearray目标
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;
m_precordset-》getfields()-》getitem(“picture”)-》appendchunk(varblob);
m_precordset-》update();//更新数据库
}
delete [] pbuffer; //开释缓冲区
pbuf=0;
}
f.close();
}