用数据库存取文件的解决方法
用数据库保存文件有很广泛的用途,例如在数据库保存图片,或者保存有格式的资料,如Wor d 文件、报表等。虽然在大多数开发工具中都提供了这种功能,但大多语焉不详。我们在开发过程也遇到这样的需求,经过仔细分析和试验,总结了在VB 和Delphi 中往数据库中存取文件的方法,提供给各位网友共享。
在数据库方面,保存文件的字段类型是一个特殊类型,在Access 中称为OLE 对象,在Sql Server 中称为image, 在Oracle 中则是长二进制。用VB 开发可以用DAO 和ADO 两种连接数据库的方法(RDO 没用过), 这两种方法中的Field 类型都有Getchunk 和Appendchunk 两个方法,Getchunk 完成从数据库中读取二进制数据,Appendchunk 则往数据库中加二进制数据(具体可以看帮助)。利用这两个函数就可以完成与数据库交流文件的功能。
以下是用DAO 读写数据的两个函数。基本思路是,先把文件以32768个字节分为一块块,逐块读入,并保存到数据库,从数据库读出时也用同样的方法
Dim Chunk() As Byte ' 不定长二进制数组,用以保存临时数据
Const CHUNK_SIZE = 32768 ' 常量,每次读取数据的长度
Function FieldToFile(filename As String, fdObject As Field) As Boolean ' 从字段中读取数据,并保存到文件中
'filename 是文件名,fdobject 指二进制字段
Dim lChunkCount As Long
Dim lChunkRemainder As Long
Dim i As Long
Dim j As Long
On Error GoTo GG
ReDim Chunk(CHUNK_SIZE)
lChunkCount = fdObject.FieldSize / CHUNK_SIZE ' 获得文件的块数
lChunkRemainder = fdObject.FieldSize Mod CHUNK_SIZE ' 整块后余下的数据 j = FreeFile(0)
Kill filename ' 如果这个文件存在,先删除
Open filename For Binary As j ' 以二进制方式打开文件
For i = 0 To lChunkCount - 1
Chunk() = fdObject.GetChunk(i * CHUNK_SIZE, CHUNK_SIZE) ' 取一块 Put j, , Chunk() ' 将块写入临时文件
Next
If lChunkRemainder > 0 Then
ReDim Chunk(lChunkRemainder)
Chunk() = fdObject.GetChunk(lChunkCount * CHUNK_SIZE, lChunkRemaind er) ' 取余下的数据
Put j, , Chunk() ' 将其写入临时文件
End If
Close j
FieldToFile = True
Exit Function
GG: ' 错误处理
Close j
FieldToFile = False
End Function
Function fileTofield(filename As String, fdObject As Field) As Boolean ' 从文件中读取数据,保存到数据库
Dim lChunkCount As Long
Dim lChunkRemainder As Long
Dim i As Long
Dim j As Long
ReDim Chunk(CHUNK_SIZE)
lChunkCount = FileLen(filename) / CHUNK_SIZE ' 获得文件的块数
lChunkRemainder = FileLen(filename) Mod CHUNK_SIZE ' 整块后余下的数据
j = FreeFile(0)
Open filename For Binary As j
For i = 0 To lChunkCount - 1
Chunk() = InputB(CHUNK_SIZE, #j) ' 取一块
fdObject.AppendChunk Chunk() ' 写入数据库
Next
If lChunkRemainder > 0 Then
ReDim Chunk(lChunkRemainder)
Chunk() = InputB(lChunkRemainder, #j) ' 取剩下
fdObject.AppendChunk Chunk() ' 写入数据库
End If
Close j
fileTofield = True
Exit Function
KK: ' 错误处理
Close j
fileTofield = False
End Function
下面是ADO 的两个方法:
' 从字段中读取数据,并保存到文件中
Function FieldToFile(FileName As String, fdObject As ADODB.Field) As Boolean
Dim lChunkCount As Long
Dim lChunkRemainder As Long
Dim i As Long
Dim j As Long
On Error GoTo GG
FieldToFile = False
If fdObject.ActualSize = 0 Then Exit Function
ReDim Chunk(CHUNK_SIZE)
lChunkCount = fdObject.ActualSize / CHUNK_SIZE ' 获得文件的块数
lChunkRemainder = fdObject.ActualSize Mod CHUNK_SIZE ' 整块后余下的数据 j = FreeFile(0)
If Len(Dir(FileName)) Then Kill FileName
Open FileName For Binary As j
ReDim Chunk(fdObject.ActualSize)
For i = 0 To lChunkCount - 1
Chunk() = fdObject.GetChunk(CHUNK_SIZE) ' 取一块
Put j, , Chunk() ' 将块写入临时文件
Next
If lChunkRemainder > 0 Then
ReDim Chunk(lChunkRemainder)
Chunk() = fdObject.GetChunk(lChunkRemainder)
' 取余下的数据
Put j, , Chunk() ' 将其写入临时文件
End If
Close j
If (FileLen(FileName)) > 0 Then FieldToFile = True
Exit Function
GG:
MsgBox Err.Description
Close j
End Function
'从文件中读取数据,保存到数据库
Function fileTofield(FileName As String, fdObject As ADODB.Field) As Boolean
Dim lChunkCount As Long
Dim lChunkRemainder As Long
Dim i As Long
Dim j As Long
ReDim Chunk(CHUNK_SIZE)
If (FileLen(FileName))
lChunkCount = FileLen(FileName) / CHUNK_SIZE ' 获得文件的块数
lChunkRemainder = FileLen(FileName) Mod CHUNK_SIZE ' 整块后余下的数据 j = FreeFile(0)
Open FileName For Binary As j
For i = 0 To lChunkCount - 1
Chunk() = InputB(CHUNK_SIZE, #j) ' 取一块
fdObject.AppendChunk Chunk()
Next
If lChunkRemainder > 0 Then
ReDim Chunk(lChunkRemainder)
Chunk() = InputB(lChunkRemainder, #j) ' 取剩下的
fdObject.AppendChunk Chunk()
End If
Close j
fileTofield = True
Exit Function
KK:
Close j
try
XQXXB:=Tadoquery.Create(self);
XQXXB.Connection:=ADOConnection1;
MfileStream.Create(OpenPictureDialog1.FileName,fmOpenRead);
MStringStream:=TStringStream.Create('');
MStringStream.CopyFrom(MfileStream,MfileStream.Size);
XQXXB.SQL.Add('Insert into XQXXB ( 照片 ) values (:zhaopian)');
XQXXB.Parameters.ParamByName('zhaopian').LoadFromStream(MStringStream,ftBlob);
XQXXB.ExecSQL;
finally
freeandnil(MfileStream);
freeandnil(XQXXB);
freeandnil(MStringStream);
end;
end;
end;
用数据库存取文件的解决方法
用数据库保存文件有很广泛的用途,例如在数据库保存图片,或者保存有格式的资料,如Wor d 文件、报表等。虽然在大多数开发工具中都提供了这种功能,但大多语焉不详。我们在开发过程也遇到这样的需求,经过仔细分析和试验,总结了在VB 和Delphi 中往数据库中存取文件的方法,提供给各位网友共享。
在数据库方面,保存文件的字段类型是一个特殊类型,在Access 中称为OLE 对象,在Sql Server 中称为image, 在Oracle 中则是长二进制。用VB 开发可以用DAO 和ADO 两种连接数据库的方法(RDO 没用过), 这两种方法中的Field 类型都有Getchunk 和Appendchunk 两个方法,Getchunk 完成从数据库中读取二进制数据,Appendchunk 则往数据库中加二进制数据(具体可以看帮助)。利用这两个函数就可以完成与数据库交流文件的功能。
以下是用DAO 读写数据的两个函数。基本思路是,先把文件以32768个字节分为一块块,逐块读入,并保存到数据库,从数据库读出时也用同样的方法
Dim Chunk() As Byte ' 不定长二进制数组,用以保存临时数据
Const CHUNK_SIZE = 32768 ' 常量,每次读取数据的长度
Function FieldToFile(filename As String, fdObject As Field) As Boolean ' 从字段中读取数据,并保存到文件中
'filename 是文件名,fdobject 指二进制字段
Dim lChunkCount As Long
Dim lChunkRemainder As Long
Dim i As Long
Dim j As Long
On Error GoTo GG
ReDim Chunk(CHUNK_SIZE)
lChunkCount = fdObject.FieldSize / CHUNK_SIZE ' 获得文件的块数
lChunkRemainder = fdObject.FieldSize Mod CHUNK_SIZE ' 整块后余下的数据 j = FreeFile(0)
Kill filename ' 如果这个文件存在,先删除
Open filename For Binary As j ' 以二进制方式打开文件
For i = 0 To lChunkCount - 1
Chunk() = fdObject.GetChunk(i * CHUNK_SIZE, CHUNK_SIZE) ' 取一块 Put j, , Chunk() ' 将块写入临时文件
Next
If lChunkRemainder > 0 Then
ReDim Chunk(lChunkRemainder)
Chunk() = fdObject.GetChunk(lChunkCount * CHUNK_SIZE, lChunkRemaind er) ' 取余下的数据
Put j, , Chunk() ' 将其写入临时文件
End If
Close j
FieldToFile = True
Exit Function
GG: ' 错误处理
Close j
FieldToFile = False
End Function
Function fileTofield(filename As String, fdObject As Field) As Boolean ' 从文件中读取数据,保存到数据库
Dim lChunkCount As Long
Dim lChunkRemainder As Long
Dim i As Long
Dim j As Long
ReDim Chunk(CHUNK_SIZE)
lChunkCount = FileLen(filename) / CHUNK_SIZE ' 获得文件的块数
lChunkRemainder = FileLen(filename) Mod CHUNK_SIZE ' 整块后余下的数据
j = FreeFile(0)
Open filename For Binary As j
For i = 0 To lChunkCount - 1
Chunk() = InputB(CHUNK_SIZE, #j) ' 取一块
fdObject.AppendChunk Chunk() ' 写入数据库
Next
If lChunkRemainder > 0 Then
ReDim Chunk(lChunkRemainder)
Chunk() = InputB(lChunkRemainder, #j) ' 取剩下
fdObject.AppendChunk Chunk() ' 写入数据库
End If
Close j
fileTofield = True
Exit Function
KK: ' 错误处理
Close j
fileTofield = False
End Function
下面是ADO 的两个方法:
' 从字段中读取数据,并保存到文件中
Function FieldToFile(FileName As String, fdObject As ADODB.Field) As Boolean
Dim lChunkCount As Long
Dim lChunkRemainder As Long
Dim i As Long
Dim j As Long
On Error GoTo GG
FieldToFile = False
If fdObject.ActualSize = 0 Then Exit Function
ReDim Chunk(CHUNK_SIZE)
lChunkCount = fdObject.ActualSize / CHUNK_SIZE ' 获得文件的块数
lChunkRemainder = fdObject.ActualSize Mod CHUNK_SIZE ' 整块后余下的数据 j = FreeFile(0)
If Len(Dir(FileName)) Then Kill FileName
Open FileName For Binary As j
ReDim Chunk(fdObject.ActualSize)
For i = 0 To lChunkCount - 1
Chunk() = fdObject.GetChunk(CHUNK_SIZE) ' 取一块
Put j, , Chunk() ' 将块写入临时文件
Next
If lChunkRemainder > 0 Then
ReDim Chunk(lChunkRemainder)
Chunk() = fdObject.GetChunk(lChunkRemainder)
' 取余下的数据
Put j, , Chunk() ' 将其写入临时文件
End If
Close j
If (FileLen(FileName)) > 0 Then FieldToFile = True
Exit Function
GG:
MsgBox Err.Description
Close j
End Function
'从文件中读取数据,保存到数据库
Function fileTofield(FileName As String, fdObject As ADODB.Field) As Boolean
Dim lChunkCount As Long
Dim lChunkRemainder As Long
Dim i As Long
Dim j As Long
ReDim Chunk(CHUNK_SIZE)
If (FileLen(FileName))
lChunkCount = FileLen(FileName) / CHUNK_SIZE ' 获得文件的块数
lChunkRemainder = FileLen(FileName) Mod CHUNK_SIZE ' 整块后余下的数据 j = FreeFile(0)
Open FileName For Binary As j
For i = 0 To lChunkCount - 1
Chunk() = InputB(CHUNK_SIZE, #j) ' 取一块
fdObject.AppendChunk Chunk()
Next
If lChunkRemainder > 0 Then
ReDim Chunk(lChunkRemainder)
Chunk() = InputB(lChunkRemainder, #j) ' 取剩下的
fdObject.AppendChunk Chunk()
End If
Close j
fileTofield = True
Exit Function
KK:
Close j
try
XQXXB:=Tadoquery.Create(self);
XQXXB.Connection:=ADOConnection1;
MfileStream.Create(OpenPictureDialog1.FileName,fmOpenRead);
MStringStream:=TStringStream.Create('');
MStringStream.CopyFrom(MfileStream,MfileStream.Size);
XQXXB.SQL.Add('Insert into XQXXB ( 照片 ) values (:zhaopian)');
XQXXB.Parameters.ParamByName('zhaopian').LoadFromStream(MStringStream,ftBlob);
XQXXB.ExecSQL;
finally
freeandnil(MfileStream);
freeandnil(XQXXB);
freeandnil(MStringStream);
end;
end;
end;