二.二进制大对象的存取方法
1.利用MFC提供的CLongBinary类
VC存取大对象数据有众多方法,如OLE、ActiveX等,而VC的MFC提供的CLongBinary类可以方便地实现存取BLOB字段。使用CLongBinary类可以存取超过MAXINT数目的数据,最大为可以得到的内存容量。但数据完全保存在内存中,对超大量数据消耗太大。
2.利用ODBC的SQLGetData和SQLPutData函数
对于不能存储在单一缓冲区中的数据,在行中的其他数据已被获取之后,可以直接用SQLGetData分批从驱动程序检索这些数据。为了从一列检索长数据,应用程序首先调用SQLFetchScroll或SQLFetch移动一行,并且调用SQLGetData获取绑定列的数据。SQLPutData允许在应用程序语句执行时,把参数或字段送到驱动程序。该函数用来把字符或二进制数值送到字符、二进制或数据源指定类型的字段。它可以传递任何类型的数据,但对字符和二进制数据可传递部分数据、绑定缓冲区并让驱动器从缓冲区中检索数据。
3.使用ADO存取BLOB数据
可以使用ADO中的AppendChunk函数来存取BLOB数据。AppendChunk包含在Field对象中,原型如下:HRESULT AppendChunk (const_variant_t & Data );从函数原型中可以看到关键的问题是需把二进制数据赋值给VARIANT类型的变量。对应于保存数据时我们所使用的AppendChunk函数,读取数据应该使用GetChunk函数,GetChunk的原型如下:_variant_t GetChunk (long Length );给出数据的长度后,GetChunk将返回包含数据的VARIANT类型变量。
三.二进制大对象的处理方法
在数据处理中,对于每个大对象字段的数据,首先选择相应的大对象读取方法,把此大对象数据取出后保留在一个临时文件中,然后在目的数据库插入数据,遇到大对象字段时,选择相应的大对象存取方法,再从临时文件中依次读出数据插入到指定字段中。
下面是使用VB实现SQL数据库中图片的上传以及保存到数据库的功能。在得到图片数据并将其保存到数据库中时,不能直接使用Insert语句对数据库进行操作,而是要使用ADO的AppendChunk方法,同样的,读出数据库中的图片数据,要使用GetChunk方法。表中图片字段sphoto的字段类型为Bianry。
程序界面如图1所示。
程序代码如下:
(1)公共变量的定义
Const ChunkSize As Long = 100
Const BlockSize As Long = 100
Const TempFile As String = "tempfile.tmp"
Dim byteData() As Byte '定义数据块数组
Dim DiskFile As String '图像文件名
Dim NumBlocks As Long '定义数据块个数
Dim FileLength As Long '标识文件长度
Dim LeftOver As Long '定义剩余字节长度
Dim SourceFile As Long '定义自由文件号
Dim byteChunk() As Byte
Dim conn As Connection
Dim rs As Recordset
(2)图片数据的存储
Public Sub SaveImage(ByVal ImageFile As String, rstu As Recordset)
If rstu.BOF = True Or rstu.EOF = True Then
Exit Sub
End If
If ImageFile = "" Then
Exit Sub
End If
'提供一个尚未使用的文件号
SourceFile = FreeFile
Open ImageFile For Binary Access Read As SourceFile
'得到文件长度
FileLength = LOF(SourceFile)
'判断文件是否存在
If FileLength = 0 Then
Close SourceFile
MsgBox DiskFile & "无内容或不存在!"
Else
NumBlocks = FileLength \ BlockSize '得到数据块的个数
LeftOver = FileLength Mod BlockSize '得到剩余字节数
rstu.Fields("sphoto").Value = Null
ReDim byteData(BlockSize) '重新定义数据块的大小
For i = 1 To NumBlocks
Get SourceFile, , byteData() '读到内存块中
rstu.Fields("sphoto").AppendChunk byteData() '写入FLD
Next i
ReDim byteData(LeftOver) '重新定义数据块的大小
Get SourceFile, , byteData() '读到内存块中
rstu.Fields("sphoto").AppendChunk byteData() '写入FLD
Close SourceFile '关闭源文件
rstu.Update
End If
End Sub
(3)图片数据的读取及显示
Public Sub ShowImage(Image1 As Image, rstu As Recordset)
Erase byteChunk()
fieldsize = rstu.Fields("sphoto").ActualSize
If fieldsize <= 0 Then
Image1.Picture = LoadPicture("")
Exit Sub
End If
'提供一个尚未使用的文件号
SourceFile = FreeFile
'打开文件
Open TempFile For Binary Access Write As SourceFile
'计算数据块
NumBlocks = fieldsize \ BlockSize
LeftOver = fieldsize Mod BlockSize '得到剩余字节数
'分块读取图像数据,并写入到文件中
If LeftOver <> 0 Then
ReDim byteChunk(LeftOver)
byteChunk() = rstu.Fields("sphoto").GetChunk(LeftOver)
Put SourceFile, , byteChunk()
End If
For i = 1 To NumBlocks
ReDim byteChunk(BlockSize)
byteChunk() = rstu.Fields("sphoto").GetChunk(BlockSize)
Put SourceFile, , byteChunk()
Next i
Close SourceFile
Image1.Picture = LoadPicture(TempFile) '将文件装入到Image1控件中
Kill (TempFile) '删除临时文件
End Sub
(4)数据库中图片数据的删除
Private Sub Label2_Click() ‘单击标签2实现数据库中图片的删除
rs.Fields("sphoto").AppendChunk ""
rs.Update
Image3.Picture = LoadPicture("")
End Sub
四、结束语
以上程序在WINXP,VB6中运行通过。数据库中BLOB数据的处理方法很多,不同的程序设计语言针对不同的DBMS,其处理方法都有差异。限于篇幅所限,在这里就不详述了。图片的出现为Visual Basic程序增添了美丽的情调,使程序更富魅力、更具专业。