笔者日前参与开发了一套高速公路收费系统,主要功能是记录通过收费站的所有车辆的信息,包括时间、车型、金额、车辆图片资料等,其中涉及到多媒体数据的处理。下面笔者将主要依靠Delphi中的流数据类型来为大家做讲解 1.问题
常用的桌面型数据库,如Access、Visual FoxPro等,使用比较简单,也可以管理多媒体信息。但由于数据库引擎不够强大,在管理少量多媒体数据时尚能正常运行,当数据量增大到一定程度后,数据库的反应就会变得异常缓慢,其性能也大幅下降。在达到某个临界点时,甚至还会出现数据库处理能力和待处理数据量的严重失衡,而导致假死状况的出现。笔者有过这样的经验,用Visual Fox Pro来管理1万名学生的照片档案和学籍信息,这时要进行查询必须经过长时间等待,最后不得不放弃。
用一些技巧可以加快系统的运行,比如“化整为零”法。即将超大数据分散到众多数据表中,虽然可以有效地提高数据库的运行速度,但层次过多使查询、统计等变得十分不便,而且编程的复杂度和工作量也会随之大幅增加。
另外一个常用方法是将多媒体数据保存为独立的文件,在数据库中只存储这些文件的路径和文件名,从而避免了将海量数据直接存入数据库。这种为数据库减负瘦身的方法可用于任何数据库,通用性好,而且对性能的提升也是可观的,是一种已经得到广泛应用的治“标”方法。然而这种方法也有明显的缺点:结构复杂、不便维护、安全性差,更体现不出数据库的优点。还是以学籍管理为例,采用这种方法管理1万甚至更多学生的照片数据,程序非常复杂,维护也十分困难,依然不是治“本”之策。
其实,要处理海量的多媒体数据,再先进的桌面型数据库都会捉襟见肘,笔者最后采用了企业级数据库。以SQL Server、Sybase、Oracle等为代表的企业级数据库具有更强大的性能、更完善的数据管理、更可靠的安全特性和更出色的网络功能,能够胜任非常复杂和庞大的数据管理任务,同时它们还提供了丰富的数据类型,以及针对多媒体管理特别优化的引擎。考虑综合性能、价格等各方面的因素,我们最终选择SQL Server 2000标准版作为系统的后台数据库。
二、怎样处理多媒体数据
1.多媒体数据的存储
多媒体信息包括图像、声音和视频等,它们都是以二进制数据集合的形式存在的,在本系统中处理的对象是图像。SQL Server提供了Image数据类型来存储可变长度二进制数据(大小范围为0~2GB)。但Image字段并不能将多媒体数据直接装入,必须经过一些中间步骤才能将数据存进去。下面以图像数据的存储为例,给大家介绍怎样在Delphi中实现这些中间步骤。
Delphi中的TStream数据类型以流的形式对字符或非字符数据进行存储,就像在内存中开辟了一个大小可变的临时缓存区。它不仅能方便地对外部文件进行读写,而且还可以将流中的全部数据直接转入数据库,所以用它作桥梁来完成数据存入工作是非常合适的。
下面的SavetoImage函数的功能是将TStream数据存入数据表的Image字段中。
function SavetoImage(const Stream:TStream;const AField:TField):boolean; var FieldStr:string; PFieldStr:PChar; begin Result:=false; if (Assigned(AField)) and (Assigned(Stream)) then begin try Stream.Seek(0,0); SetLength(FieldStr,Stream.Size); PFieldStr:=PChar(FieldStr); Stream.Read(PFieldStr^,Stream.Size); AField.Value:=FieldStr; Result:=true; except end; end; end; |
下面是调用SavetoImage函数完成图像数据存储的程序片段。
Var FS:TFileStream; begin FS:=TFileStream.Create('C:\Car001.jpg',fmOpenRead); SavetoImage(FS,Adodataset1.FieldBy Name('st_img')); FS.Free; end; |
其中,Adodataset1是与数据库进行连接的ADO数据集控件,st_img为Image字段。
2.多媒体数据的转移
利用SQL Server所带的BCP实用工具,可以很方便地将数据库部分或全部数据复制出来,包括二进制数据。对复制出的多媒体数据可以通过网络或移动存储设备将它们转移到远端的监控电脑上,再利用BCP将它们复制到监控数据库中,以便对多媒体数据进行回放或做其它处理。下面是简化了的将数据从数据库复制到外部文件和从外部文件复制入数据库的程序片段。
var s1:string; begin s1:='bcp "select * from st2002..st2002_sf where st_flag=1" queryout c:\Media_data.dat -N -P -S sunnynt\hy2002'; winexec(PChar(s1),sw_show); end; |
其中“select * from st2002..st2002_sf where st_flag=1”表示从st2002数据库的st2002_sf表中提取数据,“c:\Media_data.dat”为输出数据文件,参数queryout表示从查询中复制数据到外部文件,-N表示进行大容量数据复制操作,-P表示使用默认密码,-S提定进行数据复制操作的数据库服务器或实例。
var s1:string; begin s1:= 'bcp ST2002..ST2002_SF in c:\Media_data.dat -n -E -P -S sunnynt \hy2002'; winexec(PChar(s1),sw_show); end; |
其中参数in表示将数据从外部文件复制到数据表中。
3.多媒体数据的回放
同存储的方法类似,多媒体数据的回放也要借助TStream数据类型作桥梁,而且它基本上是存储的逆过程。
LoadfromImage函数的功能是将数据表的Image字段数据装入TStream中。
function LoadfromImage(const AField:TField;const Stream:TStream):boolean; var ResultStr:string; PResultStr:PChar; begin Result:=false; if (Assigned(AField)) and (Assigned(Stream)) then begin try ResultStr:=AField.Value; PResultStr:=PChar(ResultStr); Stream.Write(PResultStr^,length(Result Str)); Stream.Seek(0,0); Result:=True; except end; end; end; |
下面是调用LoadfromImage函数将数据表Image字段中的图像数据转出到外部文件中并利用图像显示控件回放图像的程序片段。
var FS:TFileStream; begin FS:=TFileStream.Create('c:\Car001.jpg',fmCreate); LoadfromImage(adodataset1.fieldby name('st_img'),FS); FS.Free; image1.picture.LoadFromFile('c:\Car001.jpg'); end; |
三、小结 其它多媒体数据类型如声音、视频等的转出过程与图像的转出完全相同,只是回放部分应针对不同媒体类型采用不同的媒体播放控件。
上面所述的原型程序在Delphi 5/6/7+SQL Server 2000标准版中调试通过,经过适当的扩充和修改后,这些程序在笔者开发的高速公路收费系统中得到了验证。同样,这些程序也可使用在如学籍管理、档案管理、人事管理、商品交易等涉及到多媒体数据的应用系统中。
如今已经是数码时代,DC、DV、MP3等数码设备正逐渐深入到我们生活和工作中,它们产生的图像、视频、声音等多媒体信息呈爆炸式增长,如何有效管理这些多媒体信息成为摆在我们面前的课题。本文简单讨论了利用SQL Server数据库对多媒体信息进行管理的几个基本问题,其原理同样适合Sybase、Oracle等数据库和Powerbuilder、VB等前端开发工具。