如何读取Access中OLE对象字段中的图片

分类: 代码, 笔记 | 标签: , , | 日期:2008-09-15 | 1 views

由于直接在Microsoft Access中插入OLE对象时,会自动的用封包的形式插入所选对象,因此对于需要SQL返回图像等格式的时候如果直接调用原始的数据会出错. 微软没有给出Package的格式,也没有相关的控件可以提供Package的解包操作.

无奈为了先天下之忧而忧,只好拿起Winhex对这个烂包下手.
下表是它的头部16进制数据

15 1C 24 00 02 00 00 00 08 00 08 00 14 00 1C 00
FF FF FF FF 50 61 63 6B 61 67 65 00 50 61 63 6B
61 67 65 00 01 05 00 00 02 00 00 00 08 00 00 00
50 61 63 6B 61 67 65 00 00 00 00 00 00 00 00 00
B5 79 01 00 02 00 69 6D 61 67 65 38 37 2E 6A 70
67 00 48 3A 5C 64 6F 63 75 6D 65 6E 74 73 5C 69
6D 61 67 65 38 37 2E 6A 70 67 00 00 00 03 00 14
00 00 00 48 3A 5C 54 65 6D 70 5C 69 6D 61 67 65
38 37 2E 6A 70 67 00 F6 78 01 00 FF D8 FF E0 00
10 4A 46 49 46 00 01 02 00 00 64 00 64 00 00 FF

开头的15 1C 表示封包开头.我这里是拿图片文件做实验,所有的图片的包都测试通过.
所有的Package的内容部分均从偏移量0X40开始,也就是offset=64的位置.即上表第五行

第五行开头四个bit,由低位到高位表示Package内容的大小,本例的大小为0179B5,即96653字节.
之后的02表示偏移2位开始读取文件名和文件全路径,中间以00隔开.

读完之后连续几个00之后出现03  00  14的数值.想来03大概是14位置之后偏移3位开始读取,读取的长度为十六进制的14,也就是20位.本例中这20位读出来的字符串是”H:Tempimage87.jpg “.不包含引号.其中20位字符最后一个是00为标志的结束符号.也就是C语言中的”".

紧接着的4个比特表示Package正文的大小,也就是我们当初插入的文件本身的大小.本例中的大小是0178F6,也就是96502字节.四个比特所能表示的最大大小约为3.9GB.相信所有能够直接插入数据库的文件大小都包含在内了.

接下来就是正文了,FF D8 FF E0 ……………  本例中的文件是一个标题为image87的JPEG文件,FF D8 FF正是jpg文件的标头.因此分析的结果应该是正确的.从FF D8 FF开始读取96502个数值(包括FF D8 FF),所得到的就是所需要的文件.

下面附上本例的图片供大家鉴别真伪
image87

updated @22:43 最后再加上解图片包的方法,语言是VB.net.需要导入System.IO.此函数返回的IOMemoryStreaming对象可以直接使用PictureBox.Image=Image.FromStream()来读入图像

Public Function GetPackageContent(ByVal bytes As Array) As MemoryStream
Dim by As System.IO.MemoryStream = New System.IO.MemoryStream()
If Not (bytes(0) = 21 And bytes(1) = 28) Then
by.Write(bytes, 0, bytes.Length)
Return by
End If
Dim bt As Array = New Int32() {}
Dim offset As Integer = 64, zerocount As Integer = 0
Dim j As Integer = offset + 3
While j < bytes.Length - 1
If bytes(j) = 0 Then
zerocount = zerocount + 1
End If
j = j + 1
If zerocount = 11 Then
Exit While
End If
End While
Dim k As Integer = bytes(j) + (bytes(j + 1) + (bytes(j + 2) + bytes(j + 3) * 256) * 256) * 256
by.Write(bytes, j + 4, k)
Return by
End Function

也许你还对这篇文章感兴趣:如何读取和存储Access数据库中的OLE对象

你也许会喜欢的日志

2人发表了评论  ↓发表评论↓

[ Ctrl+Enter提交 ]

使用新浪微博登陆