-
c语言入门之C++ Builder操纵多媒体数据库
随着计算机软、硬件技术的日益发展,对多媒体信息的处理能力不断增强,利用快速开发工具C++ Builder所具有的强大数据库开发功能,使得对多媒体数据(库)的创建、存、取、显示、播放等控制都非常容易实现。本文将以构建具有5个字段“编号、姓名、像片、声音、活动影像”的数据库为例,根据多媒体数据与数据库本身是否共同存储,介绍两种多媒体数据库处理方法,在这里称为集成法和分离法。
集成法
此方法是将多媒体数据直接存入数据库中,“编号”和“姓名”字段都取ftString字段类型,“像片”字段采用ftGraphic字段类型用于存放BMP文件,“声音”和“活动影像”字段均采用ftBlob字段类型(其他格式的多媒体文件均可以采用这种二进制类型存储),分别用于存放WAV和AVI文件,这样的数据库结构既可以采用C++ Builder提供的“Database Desktop”创建,也可以用下面的代码创建:
TTable *newTable = new TTable(this);
newTable->Active = false;
newTable->DatabaseName = “e:\\mydata”;
newTable->TableName = “example1.db”;
newTable->TableType = ttParadox;
//定义数据表类型
newTable->FieldDefs->Clear();
newTable->FieldDefs->Add(“编号”,ftString,8,false); //定义字段、类型、长度等
newTable->FieldDefs->Add(“姓名”,ftString,8,false);
newTable->FieldDefs->Add(“像片”,ftGraphic,0,false);
newTable->FieldDefs->Add(“声音”,ftBlob,0,false);
newTable->FieldDefs->Add(“数字电影”,ftBlob,0,false);
newTable->CreateTable(); //创建数据表
delete newTable;
由于要编程实现往数据库中添加记录的功能,因此假定在数据库程序设计阶段数据表example1
.db已经建好,同时假定所需要的多媒体文件均存放于e:\mydata\media路径之下。
所要完成的程序的功能界面如图1所示:
图 1 操作界面
点击“打开数据库”按钮将打开库文件example1.db并显示原有记录的相应信息。点击“增加记录”按钮将追加新的记录,通过数据导航按钮进行记录的移动、修改等操作,在每一时刻,点击“听听声”按钮可以听到当前记录所对应的声音,点击“看看影”按钮可以看到当前记录对应的活动影像。这个应用已具备一个多媒体数据库应用系统的基本功能,以下是主要设计步骤:
1. 组件设置
向窗体增加一个TTable组件Table1,一个TDataSource组件DataSource1,两个TDBEdit组件DBEdit1和DBEdit2,一个TDBImage组件DBImage1,一个TDBNavigator组件DBNavigator1,一个TMediaPlayer组件MediaPlayer1,一个TOleContainer组件OleContainer1,四个TButton组件和三个TLable组件。这些组件需要设置的部分属性如下表:
作者:
来自:计算机世界网
注: 表中标记“▲”的几个属性表示只有数据表example1.db已经存在,才能在设计阶段进行设置。
2. 创建字段变量
双击窗体的Table1组件,在弹出的 “Form1->Table1” 小窗口的空白处单击鼠标右键,选择“Add Fields...”菜单命令,然后选中“像片、声音、活动影像”三个字段,点击OK按钮。回到“Form1->Table1”小窗口,选中“图片”,将其Name属性修改为Table1BMPField。类似地将“声音”和“活动影像”的Name属性分别修改为Table1WAVField和Table1AVIField,这样就创建了对应的字段变量,利用它们就可以动态地向相应字段中存入多媒体数据了(如果数据表example1.db不存在,应该选择“New Fields...”菜单命令创建,这样做必须创建所有的字段,较为麻烦)。
3. 代码设计
“打开数据库”按钮的OnClick事件过程代码如下:
void __fastcall TForm1::Button1Click(TObject *Sender)
{ Table1->DatabaseName = “e:\\mydata”;
Table1->TableName = “example1.db”;
Table1->Active = true; //打开数据表
}
在“增加记录”按钮的OnClick的事件过程中输入代码:
void __fastcall TForm1::Button2Click(TObject *Sender)
{ Table1->DatabaseName = “e:\\mydata”;
Table1->TableName = “example1.db”;
Table1->Active = true;
Table1->AppendRecord(OPENARRAY(TVarRec,(“20010521”,“刘德友”)));
//增加一条记录
Table1->Edit( ); //进入编辑状态
Table1BMPField->LoadFromFile(“\\media\\ldy.bmp”);
//将图片文件载入像片字段
Table1WAVField->LoadFromFile(“\\media\\ldy.wav”);
//将声音文件载入声音字段
Table1AVIField->LoadFromFile(“\\media\\ldy.avi”);
//将电影文件载入活动影像字段
Table1->AppendRecord(OPENARRAY(TVarRec,(“20010522”,“王英”)));
//增加第二条记录
Table1->Edit( );
Table1BMPField->LoadFromFile(“\\media\\wy.bmp”);
Table1WAVField->LoadFromFile(“\\media\\wy.wav”);
Table1AVIField->LoadFromFile(“\\media\\wy.avi”);
Table1->AppendRecord(OPENARRAY(TVarRec,(“20010523”,“张雪花”)));
//添加第三条记录
Table1->Edit( );
Table1BMPField->LoadFromFile(“\\media\\zxh.bmp”);
Table1WAVField->LoadFromFile(“\\media\\zxh.wav”);
Table1AVIField->LoadFromFile(“\\media\\zxh.avi”);
}
用类似的语句可以添加多条记录。显然,若需要其他格式的多媒体数据文件也可用此法,作为二进制文件将其存入数据库。如果利用TOpenDialog组件则能够在运行过程中实现“动态”加载多媒体数据文件到相应字段。
按钮“听听声”的OnClick事件过程的代码如下:
void __fastcall TForm1::Button3Click(TObject *Sender)
{ AnsiString waveName = “temp.wav”;
Table1WAVField-> SaveToFile(waveName);
//存成临时文件
Sleep(50); //作为缓冲,暂停50毫秒
MediaPlayer1->FileName = waveName;
MediaPlayer1->Open();
MediaPlayer1->Play();
}
按钮“看看影”的OnClick事件过程的代码如下:
void __fastcall TForm1::Button4Click(TObject *Sender)
{ AnsiString aviName = “temp.avi”;
Table1AVIField->SaveToFile(aviName);
Sleep(50);
OleContainer1->CreateLinkToFile(aviName,false);
OleContainer1->DoVerb(ovPrimary);
}
注意这里使用TOleContainer1组件实现AVI播放,当然也可以用MediaPlayer1组件进行播放,此处只是提供了一种方法:利用软件的OLE技术对一些特殊格式的多媒体数据文件采用TOleContainer处理,例如DOC、PSD、DWG、SWF等,只要目标计算机安装了该软件的服务程序(想知道计算机支持哪些格式媒体文件只要在Word软件中查看“插入——>对象...”菜单便知),笔者利用此技术成功地实现了Flash动画存储和播放(已装有Flash 5)。当然也可使用第三方开发的组件或控件,C++ Builder也支持OCX控件,例如利用MP3Play控件实现MP3的播放。
至此,一个小型的多媒体数据库系统用“集成法”创建完成。
分离法
这种方法就是将多媒体数据与数据库分开存放。在数据库中相应的字符字段只存放该多媒体数据的文件名,它是数据库与数据之间的“接口”。这种情况下数据库结构可以在运行中动态创建,因此可在功能界面上(功能界面上的其他部分与图1完全相同)再增加一个按钮“创建数据库结构”并在其OnClick事件过程置入如下代码:
void __fastcall TForm1::Button5Click(TObject *Sender)
{ TTable *newTable = new TTable(this);
newTable->Active = false;
newTable->DatabaseName =“e:\\mydata”;
newTable->TableName = “example2.db”;
newTable->TableType = ttParadox;
newTable->FieldDefs->Clear();
newTable->FieldDefs->Add(“编号”,ftString,8,false);
//字段均为字符型
newTable->FieldDefs->Add(“姓名”,ftString,8,false);
newTable->FieldDefs->Add(“像片”,ftString,12,false);
newTable->FieldDefs->Add(“声音”,ftString,12,false);
newTable->FieldDefs->Add(“活动影像”,ftString,12,false);
newTable->CreateTable();
delete newTable;
}
由于允许动态创建库结构,组件Table1的DatabaseName属性和DBEdit1、DBEdit2的DataField属性用代码进行设置。因为“像片”字段存放的只是其文件名,所以组件DBImage1用Image1组件代替。这时,只需将“打开数据库”按钮的OnClick事件过程修改为:
void __fastcall TForm1::Button1Click(TObject *Sender)
{ Table1->DatabaseName = “e:\\mydata”;
Table1->TableName = “example2.db”;
DBEdit1->DataField = “编号”;
DBEdit2->DataField = “姓名”;
Table1->Active = true;
Image1->Picture->LoadFromFile(Table1->DatabaseName + “\\media\\” + Table1->FieldByName(“像片”)->AsString);
}
将“增加记录”按钮的OnClick事件过程修改为:
void __fastcall TForm1::Button2Click(TObject *Sender)
{ Table1->Active = false;
Table1->DatabaseName = “e:\\mydata”;
Table1->TableName = “example2.db”;
Table1->Active = true;
Table1->AppendRecord(OPENARRAY(TVarRec,(“20010521”,“刘德友”,“ldy.bmp”,“ldy.wav”,“ldy.avi”)));
Table1->AppendRecord(OPENARRAY(TVarRec,(“20010522”,“王英”,“wy.bmp”,“wy
.wav”,“wy.avi”)));
Table1->AppendRecord(OPENARRAY(TVarRec,(“20010523”,“张学华”,“zxh.bmp”,“zxh.wav”,“zxh.avi”)));
Table1->First();
//记录指针移到数据表首条记录
Image1->Picture->LoadFromFile(Table1->DatabaseName + “\\media\\”+Table1->FieldByName(“像片”)->AsString);
}
将“听听声”按钮的OnClick事件过程修改为:
void __fastcall TForm1::Button3Click(TObject *Sender)
{ AnsiString wavName = Table1->DatabaseName + “\\media\\” + Table1->FieldByName(“声音”)->AsString;
MediaPlayer1->FileName = wavName;
MediaPlayer1->Open();
MediaPlayer1->Play();
}
将“看看影”按钮的OnClick事件过程修改为:
void __fastcall TForm1::Button4Click(TObject *Sender)
{ AnsiString aviName = Table1->DatabaseName + “\\media\\” + Table1->FieldByName(“活动影像”)->AsString;
OleContainer1->CreateLinkToFile(aviName,false);
OleContainer1->DoVerb(ovPrimary);
}
为了使操作界面上显示的像片能随记录指针的移动而改变,可以添加组件DBNavigator1的OnClick事件,其过程代码只有一条语句:
void __fastcall TForm1::DBNavigator1Click(TObject *Sender, TNavigateBtn Button)
{ Image1->Picture->LoadFromFile(Table1->DatabaseName + “\\media\\” + Table1->FieldByName(“像片”)->AsString);
}
至此,一个小型的多媒体数据库系统用“分离法”创建完成。
小 结
以上介绍了多媒体数据从创建、存入,到读取、显示、播放等两种不同的控制方法,这两种处理方式各有优劣。若多媒体数据与数据库共同存储,数据便于管理,整个数据库系统只有一个数据库文件,但它的缺点是数据库文件会变得非常之大,使应用系统读取的运行效率降低; 若多媒体数据与数据库分开存储,其缺点是文件数量较多,维护、管理不太方便,但它的优点是数据库文件较小,数据库打开和应用系统读取的运行效率大大提高。
一般的原则是,如果多媒体数据的尺寸较小并且又有专门的数据库组件可与之关联,如职工的照片BMP文件可用组件TDBImage、格式化文档RTF文件可用组件TDBRichEdit等,这时可以采用“集成法”将数据直接存入数据库; 若多媒体数据的尺寸较大,如音频、视频等,可将数据与数据库分开存储,在数据库中只保留多媒体数据的文件名,是一种“链接”的方式,这样做有一定的灵活性,比如想修改某条记录的信息,只需直接修改数据文件,而不必打开数据库。
集成法
此方法是将多媒体数据直接存入数据库中,“编号”和“姓名”字段都取ftString字段类型,“像片”字段采用ftGraphic字段类型用于存放BMP文件,“声音”和“活动影像”字段均采用ftBlob字段类型(其他格式的多媒体文件均可以采用这种二进制类型存储),分别用于存放WAV和AVI文件,这样的数据库结构既可以采用C++ Builder提供的“Database Desktop”创建,也可以用下面的代码创建:
TTable *newTable = new TTable(this);
newTable->Active = false;
newTable->DatabaseName = “e:\\mydata”;
newTable->TableName = “example1.db”;
newTable->TableType = ttParadox;
//定义数据表类型
newTable->FieldDefs->Clear();
newTable->FieldDefs->Add(“编号”,ftString,8,false); //定义字段、类型、长度等
newTable->FieldDefs->Add(“姓名”,ftString,8,false);
newTable->FieldDefs->Add(“像片”,ftGraphic,0,false);
newTable->FieldDefs->Add(“声音”,ftBlob,0,false);
newTable->FieldDefs->Add(“数字电影”,ftBlob,0,false);
newTable->CreateTable(); //创建数据表
delete newTable;
由于要编程实现往数据库中添加记录的功能,因此假定在数据库程序设计阶段数据表example1
.db已经建好,同时假定所需要的多媒体文件均存放于e:\mydata\media路径之下。
所要完成的程序的功能界面如图1所示:
图 1 操作界面
点击“打开数据库”按钮将打开库文件example1.db并显示原有记录的相应信息。点击“增加记录”按钮将追加新的记录,通过数据导航按钮进行记录的移动、修改等操作,在每一时刻,点击“听听声”按钮可以听到当前记录所对应的声音,点击“看看影”按钮可以看到当前记录对应的活动影像。这个应用已具备一个多媒体数据库应用系统的基本功能,以下是主要设计步骤:
1. 组件设置
向窗体增加一个TTable组件Table1,一个TDataSource组件DataSource1,两个TDBEdit组件DBEdit1和DBEdit2,一个TDBImage组件DBImage1,一个TDBNavigator组件DBNavigator1,一个TMediaPlayer组件MediaPlayer1,一个TOleContainer组件OleContainer1,四个TButton组件和三个TLable组件。这些组件需要设置的部分属性如下表:
作者:
来自:计算机世界网
注: 表中标记“▲”的几个属性表示只有数据表example1.db已经存在,才能在设计阶段进行设置。
2. 创建字段变量
双击窗体的Table1组件,在弹出的 “Form1->Table1” 小窗口的空白处单击鼠标右键,选择“Add Fields...”菜单命令,然后选中“像片、声音、活动影像”三个字段,点击OK按钮。回到“Form1->Table1”小窗口,选中“图片”,将其Name属性修改为Table1BMPField。类似地将“声音”和“活动影像”的Name属性分别修改为Table1WAVField和Table1AVIField,这样就创建了对应的字段变量,利用它们就可以动态地向相应字段中存入多媒体数据了(如果数据表example1.db不存在,应该选择“New Fields...”菜单命令创建,这样做必须创建所有的字段,较为麻烦)。
3. 代码设计
“打开数据库”按钮的OnClick事件过程代码如下:
void __fastcall TForm1::Button1Click(TObject *Sender)
{ Table1->DatabaseName = “e:\\mydata”;
Table1->TableName = “example1.db”;
Table1->Active = true; //打开数据表
}
在“增加记录”按钮的OnClick的事件过程中输入代码:
void __fastcall TForm1::Button2Click(TObject *Sender)
{ Table1->DatabaseName = “e:\\mydata”;
Table1->TableName = “example1.db”;
Table1->Active = true;
Table1->AppendRecord(OPENARRAY(TVarRec,(“20010521”,“刘德友”)));
//增加一条记录
Table1->Edit( ); //进入编辑状态
Table1BMPField->LoadFromFile(“\\media\\ldy.bmp”);
//将图片文件载入像片字段
Table1WAVField->LoadFromFile(“\\media\\ldy.wav”);
//将声音文件载入声音字段
Table1AVIField->LoadFromFile(“\\media\\ldy.avi”);
//将电影文件载入活动影像字段
Table1->AppendRecord(OPENARRAY(TVarRec,(“20010522”,“王英”)));
//增加第二条记录
Table1->Edit( );
Table1BMPField->LoadFromFile(“\\media\\wy.bmp”);
Table1WAVField->LoadFromFile(“\\media\\wy.wav”);
Table1AVIField->LoadFromFile(“\\media\\wy.avi”);
Table1->AppendRecord(OPENARRAY(TVarRec,(“20010523”,“张雪花”)));
//添加第三条记录
Table1->Edit( );
Table1BMPField->LoadFromFile(“\\media\\zxh.bmp”);
Table1WAVField->LoadFromFile(“\\media\\zxh.wav”);
Table1AVIField->LoadFromFile(“\\media\\zxh.avi”);
}
用类似的语句可以添加多条记录。显然,若需要其他格式的多媒体数据文件也可用此法,作为二进制文件将其存入数据库。如果利用TOpenDialog组件则能够在运行过程中实现“动态”加载多媒体数据文件到相应字段。
按钮“听听声”的OnClick事件过程的代码如下:
void __fastcall TForm1::Button3Click(TObject *Sender)
{ AnsiString waveName = “temp.wav”;
Table1WAVField-> SaveToFile(waveName);
//存成临时文件
Sleep(50); //作为缓冲,暂停50毫秒
MediaPlayer1->FileName = waveName;
MediaPlayer1->Open();
MediaPlayer1->Play();
}
按钮“看看影”的OnClick事件过程的代码如下:
void __fastcall TForm1::Button4Click(TObject *Sender)
{ AnsiString aviName = “temp.avi”;
Table1AVIField->SaveToFile(aviName);
Sleep(50);
OleContainer1->CreateLinkToFile(aviName,false);
OleContainer1->DoVerb(ovPrimary);
}
注意这里使用TOleContainer1组件实现AVI播放,当然也可以用MediaPlayer1组件进行播放,此处只是提供了一种方法:利用软件的OLE技术对一些特殊格式的多媒体数据文件采用TOleContainer处理,例如DOC、PSD、DWG、SWF等,只要目标计算机安装了该软件的服务程序(想知道计算机支持哪些格式媒体文件只要在Word软件中查看“插入——>对象...”菜单便知),笔者利用此技术成功地实现了Flash动画存储和播放(已装有Flash 5)。当然也可使用第三方开发的组件或控件,C++ Builder也支持OCX控件,例如利用MP3Play控件实现MP3的播放。
至此,一个小型的多媒体数据库系统用“集成法”创建完成。
分离法
这种方法就是将多媒体数据与数据库分开存放。在数据库中相应的字符字段只存放该多媒体数据的文件名,它是数据库与数据之间的“接口”。这种情况下数据库结构可以在运行中动态创建,因此可在功能界面上(功能界面上的其他部分与图1完全相同)再增加一个按钮“创建数据库结构”并在其OnClick事件过程置入如下代码:
void __fastcall TForm1::Button5Click(TObject *Sender)
{ TTable *newTable = new TTable(this);
newTable->Active = false;
newTable->DatabaseName =“e:\\mydata”;
newTable->TableName = “example2.db”;
newTable->TableType = ttParadox;
newTable->FieldDefs->Clear();
newTable->FieldDefs->Add(“编号”,ftString,8,false);
//字段均为字符型
newTable->FieldDefs->Add(“姓名”,ftString,8,false);
newTable->FieldDefs->Add(“像片”,ftString,12,false);
newTable->FieldDefs->Add(“声音”,ftString,12,false);
newTable->FieldDefs->Add(“活动影像”,ftString,12,false);
newTable->CreateTable();
delete newTable;
}
由于允许动态创建库结构,组件Table1的DatabaseName属性和DBEdit1、DBEdit2的DataField属性用代码进行设置。因为“像片”字段存放的只是其文件名,所以组件DBImage1用Image1组件代替。这时,只需将“打开数据库”按钮的OnClick事件过程修改为:
void __fastcall TForm1::Button1Click(TObject *Sender)
{ Table1->DatabaseName = “e:\\mydata”;
Table1->TableName = “example2.db”;
DBEdit1->DataField = “编号”;
DBEdit2->DataField = “姓名”;
Table1->Active = true;
Image1->Picture->LoadFromFile(Table1->DatabaseName + “\\media\\” + Table1->FieldByName(“像片”)->AsString);
}
将“增加记录”按钮的OnClick事件过程修改为:
void __fastcall TForm1::Button2Click(TObject *Sender)
{ Table1->Active = false;
Table1->DatabaseName = “e:\\mydata”;
Table1->TableName = “example2.db”;
Table1->Active = true;
Table1->AppendRecord(OPENARRAY(TVarRec,(“20010521”,“刘德友”,“ldy.bmp”,“ldy.wav”,“ldy.avi”)));
Table1->AppendRecord(OPENARRAY(TVarRec,(“20010522”,“王英”,“wy.bmp”,“wy
.wav”,“wy.avi”)));
Table1->AppendRecord(OPENARRAY(TVarRec,(“20010523”,“张学华”,“zxh.bmp”,“zxh.wav”,“zxh.avi”)));
Table1->First();
//记录指针移到数据表首条记录
Image1->Picture->LoadFromFile(Table1->DatabaseName + “\\media\\”+Table1->FieldByName(“像片”)->AsString);
}
将“听听声”按钮的OnClick事件过程修改为:
void __fastcall TForm1::Button3Click(TObject *Sender)
{ AnsiString wavName = Table1->DatabaseName + “\\media\\” + Table1->FieldByName(“声音”)->AsString;
MediaPlayer1->FileName = wavName;
MediaPlayer1->Open();
MediaPlayer1->Play();
}
将“看看影”按钮的OnClick事件过程修改为:
void __fastcall TForm1::Button4Click(TObject *Sender)
{ AnsiString aviName = Table1->DatabaseName + “\\media\\” + Table1->FieldByName(“活动影像”)->AsString;
OleContainer1->CreateLinkToFile(aviName,false);
OleContainer1->DoVerb(ovPrimary);
}
为了使操作界面上显示的像片能随记录指针的移动而改变,可以添加组件DBNavigator1的OnClick事件,其过程代码只有一条语句:
void __fastcall TForm1::DBNavigator1Click(TObject *Sender, TNavigateBtn Button)
{ Image1->Picture->LoadFromFile(Table1->DatabaseName + “\\media\\” + Table1->FieldByName(“像片”)->AsString);
}
至此,一个小型的多媒体数据库系统用“分离法”创建完成。
小 结
以上介绍了多媒体数据从创建、存入,到读取、显示、播放等两种不同的控制方法,这两种处理方式各有优劣。若多媒体数据与数据库共同存储,数据便于管理,整个数据库系统只有一个数据库文件,但它的缺点是数据库文件会变得非常之大,使应用系统读取的运行效率降低; 若多媒体数据与数据库分开存储,其缺点是文件数量较多,维护、管理不太方便,但它的优点是数据库文件较小,数据库打开和应用系统读取的运行效率大大提高。
一般的原则是,如果多媒体数据的尺寸较小并且又有专门的数据库组件可与之关联,如职工的照片BMP文件可用组件TDBImage、格式化文档RTF文件可用组件TDBRichEdit等,这时可以采用“集成法”将数据直接存入数据库; 若多媒体数据的尺寸较大,如音频、视频等,可将数据与数据库分开存储,在数据库中只保留多媒体数据的文件名,是一种“链接”的方式,这样做有一定的灵活性,比如想修改某条记录的信息,只需直接修改数据文件,而不必打开数据库。
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
SQL Server -- 解决存储过程传入参数作为s
JavaScript判断两个数组相等的四类方法
js如何操作video标签
React实战--利用甘特图和看板,强化Paas平
【记录】正则替换的偏方
前端下载 Blob 类型整理
抽象语法树AST必知必会
关于JS定时器的整理
JS中使用Promise.all控制所有的异步请求都完
js中字符串的方法
import-local执行流程与node模块路径解析流程