師惠萍,程耀瑜,王詩琴,劉永林,雷紅淼
(中北大學(xué) 山西省現(xiàn)代無損檢測(cè)工程技術(shù)研究中心, 太原 030051)
在設(shè)計(jì)數(shù)據(jù)庫的過程中,會(huì)經(jīng)常要存儲(chǔ)一些圖形、長(zhǎng)文本、多媒體等各種各樣的程序文件,如果在數(shù)據(jù)庫中僅存儲(chǔ)這些文件的路徑信息,雖然可以大大減小數(shù)據(jù)庫的大小,但是由于文件存儲(chǔ)在磁盤上,除了維護(hù)數(shù)據(jù)庫外還要維護(hù)文件的路徑信息,保持二者的一致,對(duì)于管理數(shù)據(jù)庫非常不便,同時(shí)也給數(shù)據(jù)的安全帶來隱患。如果把這些文件的內(nèi)容作為一個(gè)記錄的一個(gè)字段值直接保存到數(shù)據(jù)庫中,這樣不僅能夠簡(jiǎn)化數(shù)據(jù)庫和文件的管理工作,還能保證數(shù)據(jù)的安全[1-2]。本文以VC++6.0為開發(fā)工具,選取SQL Server 2000數(shù)據(jù)庫存放圖像數(shù)據(jù),采用ADO方式連接數(shù)據(jù)庫,介紹如何從數(shù)據(jù)庫中存取圖像數(shù)據(jù)并顯示出來。
目前,圖像的存取方法一般有兩種:一種是間接存取法。這種方式是把圖像存儲(chǔ)在指定的文件夾下,把保存圖像文件所在的路徑和文件名保存在數(shù)據(jù)庫中,它對(duì)圖像的存取則是根據(jù)圖像文件的存儲(chǔ)路徑和文件名來進(jìn)行。這種方法對(duì)數(shù)據(jù)的管理不方便,對(duì)圖像信息安全性和可靠性也不能保證,不適合保存重要的圖像信息;第二種方法是直接存取法。它是把圖像信息直接保存在數(shù)據(jù)庫表中。這是目前圖像數(shù)據(jù)庫技術(shù)發(fā)展的主流,可以保證圖像數(shù)據(jù)的一致性和安全性。但在讀取技術(shù)實(shí)現(xiàn)上,很多數(shù)據(jù)庫不支持圖像數(shù)據(jù)的直接存取,必須由第三方開發(fā)的工具來完成數(shù)據(jù)庫中圖像數(shù)據(jù)的存取[3-5]。
圖像可以看作是一種特殊的BLOB數(shù)據(jù),BLOB(Binary Large Object)數(shù)據(jù)是指非常巨大的不定的二進(jìn)制或者字符型數(shù)據(jù)。通常是文檔(.txt、.doc)和圖片(.jpeg、.gif、.bmp),可以存儲(chǔ)在數(shù)據(jù)庫中。在SQL Server 2000中,BLOB可以是text、ntext或是image數(shù)據(jù)類型。
ADO是應(yīng)用級(jí)的編程接口,它以O(shè)LE DB為基礎(chǔ),對(duì)OLE DB進(jìn)行了封裝。ADO訪問數(shù)據(jù)庫是通過訪問OLE DB數(shù)據(jù)并提供程序來進(jìn)行的,提供了一種對(duì)OLE DB數(shù)據(jù)提供程序的簡(jiǎn)單高層訪問接口。ADO封裝了大量的COM接口,基于通用對(duì)象模型,不僅提供了多種語言的訪問技術(shù)(VB,VC等),也可用腳本語言來訪問(VbScript VcScript)[6]。
ADO提供了3個(gè)基本接口:
_ConnectionPtr接口返回一個(gè)記錄集或一個(gè)空指針。通常使用它創(chuàng)建一個(gè)數(shù)據(jù)連接。
_CommandPtr接口返回一個(gè)記錄集。它提供了一種簡(jiǎn)單的辦法來執(zhí)行返回記錄集的存儲(chǔ)過程和SQL語句。
_RecordsetPtr接口是一個(gè)記錄集對(duì)象。它對(duì)記錄集提供了更多的控制功能,如記錄鎖定,游標(biāo)控制等。
在VC++中,使用ADO之前必須在工程的stdafx.h文件里添加對(duì)ADO的支持代碼,即使用#import指令引人ADO動(dòng)態(tài)鏈接庫文件,使編譯器能正確編譯。代碼如下:
#import "c:program filescommon filessystemadomsado 15 .d11"
no_namespace rename("EOF","adoEOF")
再初始化COM庫,代碼如下:
CoInitialize ( NULL );
用ADO訪問數(shù)據(jù)庫,首先要?jiǎng)?chuàng)建連接(Connection)對(duì)象建立與數(shù)據(jù)源的連接,然后創(chuàng)建記錄集(Recordset)對(duì)象,實(shí)現(xiàn)對(duì)數(shù)據(jù)庫的訪問。
ADO的Field(域)對(duì)象為BLOB數(shù)據(jù)提供了AppendChunk和GetChunk兩種方法。通過他們可以像讀寫文件一樣,把其他文件的內(nèi)容寫入數(shù)據(jù)庫,或把數(shù)據(jù)庫的內(nèi)容讀出來再保存到文件中。在VC++中,AppenChunck把圖像文件的數(shù)據(jù)寫入數(shù)據(jù)庫的image類型字段,GetChunck讀出image字段數(shù)據(jù),顯示圖像或保存為圖片文件。
結(jié)合本文開發(fā)的“射線圖像處理與圖像數(shù)據(jù)庫管理系統(tǒng)”說明應(yīng)用程序中存取數(shù)據(jù)庫圖像的實(shí)現(xiàn)方法。系統(tǒng)的“圖像存取及顯示”模塊可以實(shí)現(xiàn)圖像遍歷顯示、圖像入庫[7-8]。
(1)在SQL Server 2000中建立一個(gè)數(shù)據(jù)庫TXDB,新建表tbTX,表的字段設(shè)計(jì)如圖1所示。
圖1 表tbTX的字段設(shè)計(jì)
(2)在VC++中添加各控件并更改其屬性,設(shè)計(jì)圖像存取及顯示模塊窗口界面,如圖2所示。
圖2 窗口界面設(shè)計(jì)
(3)使用ADO對(duì)象:進(jìn)入ADO動(dòng)態(tài)庫,初始化和釋放COM庫,新建UDL文件,設(shè)置數(shù)據(jù)庫鏈接。具體步驟不做介紹。
(4)添加兩個(gè)處理BLOB數(shù)據(jù)的自定義函數(shù):
BOOL TXAppenChunk(FieldPtr pField, LPVOID lpData,UINT nBytes);
BOOL TXGetChunk(FieldPtr pField, LPVOID lpData);
其中,TXAppenChunk函數(shù)用來把數(shù)據(jù)寫入數(shù)據(jù)庫表的BLOB字段,其參數(shù)pField即為代表某BLOB字段類型的字段對(duì)象指針,lpData參數(shù)指向要寫入的數(shù)據(jù)。
TXGetChunk函數(shù)用來讀取BLOB字段的數(shù)據(jù),其參數(shù)pField即為代表某BLOB字段類型的字段對(duì)象指針,lpData參數(shù)指定用來存放讀取到BLOB數(shù)據(jù)的地址。
void CTXDlg::OnAddNew()
{ CFile file;
if (file.Open(m_strPathName, CFile::modeRead))
//打開文件
{ long length = (long) file.GetLength ();
//獲取文件長(zhǎng)度
BYTE *pbuf = new BYTE[length];
//為讀文件建立緩存區(qū)
if (pbuf != NULL && file.Read(pbuf, length) = = (DWORD)length)
{ m_pRecordset->AddNew(); //添加記錄
m_pRecordset->Fields->GetItem(long(1))->PutValue(_variant_t(dlg.GetFileName()));
//調(diào)用TXAppendChunk函數(shù)
TXAppendChunk(FieldPtr(m_pRecordset->GetFields()->GetItem(_bstr_t("Bmp"))),
pbuf, length);
m_pRecordset->Update();}}}
void CTXDlg :: ShowPic ()
//使用ShowPic函數(shù)來顯示圖像。
{ 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);
點(diǎn)的中心度是節(jié)點(diǎn)中心性的判斷指標(biāo)之一,是衡量節(jié)點(diǎn)與其他節(jié)點(diǎn)聯(lián)系廣度的重要參數(shù),若一個(gè)節(jié)點(diǎn)同較多節(jié)點(diǎn)相連則該節(jié)點(diǎn)中心度較高。分析表明點(diǎn)的中心度較高的前幾位關(guān)鍵詞依次為正念訓(xùn)練、心理健康、正念、正念干預(yù)、社會(huì)生活問題、MBSR,這由圖譜中節(jié)點(diǎn)面積大小可得到驗(yàn)證。
m_strName=strValue;
UpdateData (FALSE);
//獲得圖片數(shù)據(jù),顯示圖片
long size = m_pRecordset->Fields->GetItem(_bstr_t("Bmp"))->ActualSize;
if ( size > 0)
{ BYTE *lpData = new BYTE[size];
//調(diào)用TXGetChunk函數(shù),把圖像數(shù)據(jù)讀入到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("該記錄為空!");}
本文采用直接將圖像數(shù)據(jù)存儲(chǔ)在數(shù)據(jù)庫關(guān)系表中的方法,消除了將圖像數(shù)據(jù)作為文件存放的種種弊端,提高圖像數(shù)據(jù)的可用性和安全性。結(jié)合實(shí)例實(shí)現(xiàn)了圖像存取,遍歷查看的功能。圖像的格式不僅支持BMP格式,還支持其他格式的圖像,如jpg等。程序運(yùn)行結(jié)果如圖3所示。
圖3 程序運(yùn)行結(jié)果
[1]原奕.Visual C++實(shí)踐與提高—數(shù)據(jù)庫開發(fā)與工程應(yīng)用[M].北京:中國(guó)鐵道出版社,2006:277-278.
[2]求是科技.Visual C++數(shù)據(jù)庫通用模塊及典型系統(tǒng)開發(fā)實(shí)例導(dǎo)航[M].北京:人民郵電出版社,2006:100-105.[3]王姝.數(shù)據(jù)庫圖像字段數(shù)據(jù)存儲(chǔ)與讀取技術(shù)應(yīng)用研究[J].科學(xué)技術(shù)與工程,2010,10(3):682-685.
[4]楊寧,申強(qiáng),謝靜.SQL Server數(shù)據(jù)庫中圖像存取技術(shù)研究[J].南京曉莊學(xué)院學(xué)報(bào),2010,5(3):82-84.
[5]劉顯榮.用VC++實(shí)現(xiàn)數(shù)據(jù)庫中圖片的存取與顯示[J].計(jì)算機(jī)應(yīng)用研究,2006(5):163-165.
[6]王櫻,徐雨明.VC++中數(shù)據(jù)庫訪問技術(shù)研究[J].微計(jì)算機(jī)信息,2006,22(4-3):256-258.
[7]鄭阿奇.Visual C++教程[M].北京:清華大學(xué)出版社,2005:246-248.
[8]高金蘭.數(shù)據(jù)庫原理與SQL Server應(yīng)用[M].武漢:武漢大學(xué)出版社,2008:103.