前言:在數(shù)據(jù)庫的開發(fā)過程中,經(jīng)常需要在數(shù)據(jù)庫中存儲一些備注信息,而這些備注信息的內(nèi)容一般較大,格式多樣-如有可能是語音文件、視頻文件、圖片文件、文本文件等,怎樣在PB中實(shí)現(xiàn)這些格式不同的備注文件的存取及預(yù)覽,一直是PB開發(fā)人員比較關(guān)心的一個問題,本文系統(tǒng)的介紹了三種存取備注二進(jìn)制信息的方法。
對備注二進(jìn)制信息的存儲可以采用以下三種方式;
方法一:文件保存在固定的路徑下,數(shù)據(jù)庫中存取文件路徑和名稱
方法二:數(shù)據(jù)庫中用blob類型或者varbinary類型字段存儲備注文件
方法三:在本地用OLE存儲結(jié)構(gòu)存儲備注文件
1、OLE的基本概念
OLE是Object Linking Embedding(對象鏈結(jié)與嵌入)的縮寫,它可以使windows應(yīng)用程序共享數(shù)據(jù)和程序。
2、OLE控件
在PB中OLE控件是一個OLE對象的包容器,可以使用服務(wù)器應(yīng)用程序提供的功能和命令來編輯對象,也可以使用自動化OLE交互,在程序中激活對象和向服務(wù)器應(yīng)用程序發(fā)送命令;在PB 的window畫板中的OLE控件允許用戶從多個應(yīng)用程序嵌入和鏈結(jié)組件
2.1建立和設(shè)置OLE控件
從window畫板中選擇OLE控件插入window。
當(dāng)建立一個OLE控件并且插入一個對象時,PB將激活服務(wù)器應(yīng)用程序以允許對對象進(jìn)行編輯和修改;在使OLE中的對象稱為非活動狀態(tài)后,可以使用控件屬性選項卡來設(shè)置控件的屬性。
2.2 激活修改window畫板中的OLE對象
在OLE控件的彈出菜單中選擇open可以激活畫板中OLE對象
使用服務(wù)器應(yīng)用程序修改OLE對象
結(jié)束修改:使對象恢復(fù)為非活動狀態(tài),只要單擊服務(wù)器應(yīng)用對象之外的任何區(qū)域即可,也可以直接關(guān)閉服務(wù)器應(yīng)用程序的窗口。
2.3 嵌入和鏈結(jié)OLE控件
可以將OLE對象嵌入或者鏈結(jié)到自己的應(yīng)用程序中。嵌入對象的數(shù)據(jù)放在應(yīng)用程序中,在開發(fā)過程中這些數(shù)據(jù)放在應(yīng)用程序的PBl庫中,當(dāng)生成應(yīng)用后,這些數(shù)據(jù)將存放在exe或PBd文件中,雖然在程序的運(yùn)行過程中可以修改,但修改的數(shù)據(jù)不會保存;鏈結(jié)對象的數(shù)據(jù)存放在PB應(yīng)用程序以外,當(dāng)鏈結(jié)一個對象時,在PB應(yīng)用程序中不存放數(shù)據(jù)文件,而是存放引用數(shù)據(jù)的指針, 使用鏈結(jié)的數(shù)據(jù),對數(shù)據(jù)的管理和保存都由服務(wù)器應(yīng)用程序負(fù)責(zé)。這樣可以用服務(wù)器應(yīng)用程序修改處理數(shù)據(jù),處理后的數(shù)據(jù)可以保存回原文件中。鏈結(jié)方式應(yīng)用于需要多個應(yīng)用程序共享的數(shù)據(jù)文件,任何一個應(yīng)用程序修改了數(shù)據(jù)文件,都將影響到所有鏈結(jié)該文件的應(yīng)用程序。
2.4 OLE控件的激活方式
OLE控件的激活方式有offsite和in-place兩種激活方式,offsite激活方式是指在PB應(yīng)用程序的界面以外單獨(dú)打開OLE對象,in -place激活方式是指PB應(yīng)用程序的界面的原位置打開OLE對象。在數(shù)據(jù)窗口中的dbOLE默認(rèn)的是offsite激活方式,而window中的 OLE默認(rèn)的激活方式是in-place。
在PB應(yīng)用程序中可以用命令OLE_control.active(offsite) 或者OLE_control.active(in-place)設(shè)置OLE對象的以何種方式打開。
2.5 設(shè)置和插入OLE對象
在程序運(yùn)行時可以用函數(shù):
OLE_control.insertfile(soucefile) 插入對象
OLE_control.objectdata = blobvar 設(shè)置對象
3、OLE存儲
3.1 OLE存儲(OLEstorage)的概念
OLE存儲(OLEstorage)是OLE數(shù)據(jù)的一個倉庫,存儲就象磁盤上的目錄結(jié)構(gòu),它可以是一個OLE對象,也可以包含在OLE對象中,每個對象都包含在 OLE存儲或者存儲內(nèi)的子存儲內(nèi)。保存在OLE存儲中數(shù)據(jù)稱作OLE流(OLE stream),OLE流同OLE對象的關(guān)系就象文件同目錄的關(guān)系。含有 OLE對象的存儲或子存儲可以看做是屬于特殊服務(wù)器的信息,在該層次之下的各部分都可以被相應(yīng)的服務(wù)器程序操作。OLE存儲對象是類用戶對象,可以說明相應(yīng)類型的變量,建立與之相應(yīng)的實(shí)例和打開存儲等,在使用完存儲后需要關(guān)閉存儲、釋放分配的內(nèi)存。
3.2 OLE存儲的打開和保存
OLE存儲可以用open函數(shù)打開,open函數(shù)的格式為: Olecontrol.Open(OLEsourcefile),
此函數(shù)在OLEsourcefile不存在時,自動創(chuàng)建該文件,所以創(chuàng)建OLE文件也用該函數(shù); OLE存儲可以用save函數(shù)保存,save函數(shù)的格式為:
OLEcontrol.save() // 保存OLE控件
OLEstorage.save() //保存OLE存儲
4、處理blob類型數(shù)據(jù)
對于大二進(jìn)制數(shù)據(jù),在PB Script中是用blob數(shù)據(jù)類型表示并加以處理。標(biāo)準(zhǔn)SQL語句中的select、insert和update語句無法直接查詢blob類型的數(shù)據(jù),在PB中操作blob類型的數(shù)據(jù)只能用專用的語句,從數(shù)據(jù)庫中查詢blob類型的數(shù)據(jù)的命令是:
selectblob restofselectstatement {using transactionobject};
更新數(shù)據(jù)庫中blob類型數(shù)據(jù)的格式是:
updateblob tablename
set blobcolumn = blobvarible
restofupatestatement {using transctionobject};
如連接的數(shù)據(jù)庫是sybase或者Sql,則selectblob和updateblob語句要求數(shù)據(jù)庫的自動提交方式為true,所以在在每次調(diào)用selectblob和updateblob語句以前必須用命令 Sqlca.autocommit=true,把數(shù)據(jù)庫的自動提交方式設(shè)置為true,在updateblob語句的結(jié)束后,再用命令Sqlca.autocommit = false,把自動提交方式設(shè)置為 false。 索數(shù)據(jù)的參數(shù)(如flag),然后在可修改列的PRotect后的框中輸入(user_name是該DataWindow中的一列,代表輸入者的名稱):
5、數(shù)據(jù)窗口的blob列
5.1 數(shù)據(jù)窗口blob列的功能
在PB 的datawindow畫板中DBOLE控件允許用戶利用這個控件瀏覽和操作數(shù)據(jù)庫中的大二進(jìn)制數(shù)據(jù),即通過DBOLE控件可以作如下操作:
往數(shù)據(jù)庫中存儲大二進(jìn)制數(shù)據(jù),如:Excel工作表、Word文檔、視頻文件、圖片文件等各種格式的文件;
● 從數(shù)據(jù)庫中檢索數(shù)據(jù)到datawindow對象;
● 使用OLE服務(wù)器程序察看修改數(shù)據(jù);
● 將修改后的數(shù)據(jù)保存回數(shù)據(jù)庫;
5.2 在數(shù)據(jù)窗口中添加blob列的的步驟
1) 選擇具有二進(jìn)制字段的數(shù)據(jù)表作為數(shù)據(jù)源建立一新的數(shù)據(jù)窗口(該窗口可以至少需要包含非數(shù)據(jù)庫表的標(biāo)識列)
2) 選擇insert -control-OLE database blob 菜單,在數(shù)據(jù)窗口的detail節(jié)中要插入blob列的位置單擊鼠標(biāo),這時將顯示如圖1所示的對話框
下面解釋這些屬性的具體含義
1) client class: 客戶類名,默認(rèn)為datawindow
2) client name:客戶名,默認(rèn)為untitled
3) table: 選擇含有blob列的數(shù)據(jù)庫表,所選表的字段將出現(xiàn)在右側(cè)的large binary/text column列表框中。
4) large binary/text column:選擇一個blob類型的字段列
5) key clause:檢索和更新blob數(shù)據(jù)的關(guān)鍵字表達(dá)式其中使用帶冒號前綴的變量指出是數(shù)據(jù)窗口對象的列,如 表達(dá)式 id=:id,id是數(shù)據(jù)庫表中的列,變量指出數(shù)據(jù)窗口對象的列
6) filetemplate :如果需要OLE應(yīng)用服務(wù)器每次打開相同的文件,則在filetemplate框中輸入文件名。
7) OLE class :如果不需要OLE應(yīng)用服務(wù)器每次打開相同的文件,則在OLE class框中選擇一個OLE類,如Pbrush。
8) Client name expression:顯示在OLE服務(wù)器應(yīng)用程序窗口標(biāo)題的文字,可以輸入為:"對應(yīng)記錄的id號是"+id
單擊ok按鈕關(guān)閉對話框,將dbole列添加到適當(dāng)?shù)奈恢茫4鏀?shù)據(jù)窗口。
預(yù)覽則可以對數(shù)據(jù)庫中的blob數(shù)據(jù)進(jìn)行存取,但是在新建的記錄中只能存取OLE class框中選擇的一種格式的blob數(shù)據(jù),不能存儲多種格式的數(shù)據(jù);但如果數(shù)據(jù)庫中存有多種格式的數(shù)據(jù),可以預(yù)覽各種格式的數(shù)據(jù)。
6、源程序建立
1) 首先在數(shù)據(jù)庫中建立如下結(jié)構(gòu)的表blobsave:
字段名稱 數(shù)據(jù)類型 備注
id char(4) primairy key index
s_path char(50)
pic binary (50)
2) 在PB建立PBl庫blobsave.PBl
3) 在PBl庫blobsave.PBl中建立應(yīng)用blobsave
在應(yīng)用的open事件中設(shè)置數(shù)據(jù)庫連接程序(本程序中采用的是odbc方式連接數(shù)據(jù)庫,讀者可根據(jù)自己所建立的數(shù)據(jù)庫的不同選用不同的連接方式,以下連接數(shù)據(jù)庫的代碼也有所改動,至于連接不同的數(shù)據(jù)庫的方法,請參考有關(guān)資料,本文不做詳細(xì)介紹):
SQLCA.DBMS = "ODBC"
SQLCA.AutoCommit = False
SQLCA.DBParm = "Connectstring="DSN=blob""
connect;
open(w_main)
其中命令按鈕cb_path的clicked中的代碼格式如下:open(w_path)
其中命令按鈕cb_dbblob的clicked中的代碼格式如下:open(w_dbblob)
其中命令按鈕cb_OLEblob的clicked中的代碼格式如下:open(w_OLEblob)
4) 建立數(shù)據(jù)窗口dw_blobsave
按照上文中建立數(shù)?荽翱詰腷lob列的方法建立數(shù)據(jù)窗口dw_blobsave如圖所示:
其中:add,del,save,cancel,,retrieve等分別為數(shù)據(jù)窗口dw_blobsave的append row,delete row,update,retrieve動作按鈕。
首先創(chuàng)建實(shí)例變量 OLEstorage stor1
然后如圖建立窗口w_path,其中數(shù)據(jù)窗口控件dw_1的rowfocuschanged中的代碼如下:
long row_num
row_num=dw_1.getrow()
if row_num >0 then
ole_1.insertfile(dw_1.object.s_path[row_num])
end if
其中數(shù)據(jù)窗口dw_1的buttonclicked中的代碼如下:
if dwo.name="cbselect" then
long row_num
row_num=dw_1.getrow()
string filepath,filename
getfileopenname("請選擇備注文件",filepath,filename)
dw_1.object.s_path[row_num]=filepath
ole_1.insertfile(filepath)
end if
保存窗口w_path
6) 建立窗口w_dbblob
打開w_path,把其另存為w_dbblob,改變數(shù)據(jù)窗口dw_1的rowfocuschanged中的代碼如下:
blob text1
long row_num
row_num=dw_1.getrow()
if row_num>0 then
string id
id = dw_1.object.id[row_num]
sqlca.autocommit=true
selectblob pic into :text1 from blobsave where id = :id;
ole_1.objectdata=text1
sqlca.autocommit=false
end if
改變數(shù)據(jù)窗口dw_1的buttonclicked中的代碼如下:
long row_num
if dwo.name="cbselect" then
row_num=dw_1.getrow()
string filepath,filename
getfileopenname("請選擇備注文件",filepath,filename)
dw_1.object.s_path[row_num]=filepath
ole_1.insertfile(filepath)
end if
if dwo.name="cbsave" then
string id
sqlca.autocommit = true
blob text1
text1 = ole_1.objectdata
dw_1.update()
commit;
row_num=dw_1.getrow()
id=dw_1.object.id[row_num]
updateblob blobsave
set pic = :text1
where id = :id ;
commit;
sqlca.autocommit = FALSE
dw_1.retrieve()
dw_1.scrolltorow(row_num)
end if
保存窗口w_dbblob
7) 建立窗口w_OLEblob
打開w_path,把其另存為w_OLEblob,在窗口w_OLEblob的open事件中寫入以下代碼:
stor1 = create olestorage
stor1.open("c:/p1.ole") //打開或創(chuàng)建ole文件
在窗口w_OLEblob的close事件中寫入以下代碼:
destroy stor1
改變數(shù)據(jù)窗口dw_1的rowfocuschanged中的代碼如下:
blob text1
long row_num
row_num=dw_1.getrow()
if row_num>0 then
string id
id = dw_1.object.id[row_num]
ole_1.open(stor1,"w"+id)
end if
改變數(shù)據(jù)窗口dw_1的buttonclicked中的代碼如下:
long row_num
if dwo.name="cbselect" then
row_num=dw_1.getrow()
string filepath,filename
getfileopenname("請選擇備注文件",filepath,filename)
dw_1.object.s_path[row_num]=filepath
ole_1.insertfile(filepath)
end if
if dwo.name="cbsave" then
string id
row_num=dw_1.getrow()
id=dw_1.object.id[row_num]
ole_1.saveas(stor1,"w"+id)
stor1.save()
end if
保存窗口w_OLEblob,運(yùn)行應(yīng)用程序即可。
7、三種方法的優(yōu)缺點(diǎn)
方法一:文件保存在固定的路徑下,數(shù)據(jù)庫中存取文件路徑和名稱可以節(jié)省數(shù)據(jù)空間,避免了數(shù)據(jù)庫過分膨脹,但備注文件必須在一定的目錄下,不能丟失,且同一目錄下文件不能重名,對文件的管理造成一定的困難,另外,在OLE控件中瀏覽顯示備注文件時,由于每次都要調(diào)用服務(wù)器程序,所以速度較慢。
方法二:在數(shù)據(jù)庫中用blob類型或者varbinary類型字段存儲備注文件,當(dāng)文件存儲在數(shù)據(jù)庫中以后,就可以刪除硬盤上原來的臨時文件,不需要復(fù)雜的二進(jìn)制文件管理,且數(shù)據(jù)庫可以存儲在網(wǎng)絡(luò)服務(wù)器上,對數(shù)據(jù)的共享非常方便。
方法三:在本地用OLE存儲結(jié)構(gòu)存儲備注文件。可以把所有的二進(jìn)制文件信息存儲在一個OLE存儲文件中,管理比較方便。當(dāng)二進(jìn)制文件信息存儲后,可以刪除原來的臨時文件;因?yàn)榇蜷_存儲文件后不需要每次執(zhí)行服務(wù)器程序來顯示存儲信息,所以存取速度較快。
新聞熱點(diǎn)
疑難解答
圖片精選