師惠萍,程耀瑜,王詩琴,劉永林,雷紅淼
(中北大學 山西省現代無損檢測工程技術研究中心, 太原 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.