首页 考试吧论坛 Exam8视线 考试商城 网络课程 模拟考试 考友录 实用文档 求职招聘 论文下载
2011中考 | 2011高考 | 2012考研 | 考研培训 | 在职研 | 自学考试 | 成人高考 | 法律硕士 | MBA考试
MPA考试 | 中科院
四六级 | 职称英语 | 商务英语 | 公共英语 | 托福 | 雅思 | 专四专八 | 口译笔译 | 博思 | GRE GMAT
新概念英语 | 成人英语三级 | 申硕英语 | 攻硕英语 | 职称日语 | 日语学习 | 法语 | 德语 | 韩语
计算机等级考试 | 软件水平考试 | 职称计算机 | 微软认证 | 思科认证 | Oracle认证 | Linux认证
华为认证 | Java认证
公务员 | 报关员 | 银行从业资格 | 证券从业资格 | 期货从业资格 | 司法考试 | 法律顾问 | 导游资格
报检员 | 教师资格 | 社会工作者 | 外销员 | 国际商务师 | 跟单员 | 单证员 | 物流师 | 价格鉴证师
人力资源 | 管理咨询师考试 | 秘书资格 | 心理咨询师考试 | 出版专业资格 | 广告师职业水平
驾驶员 | 网络编辑
卫生资格 | 执业医师 | 执业药师 | 执业护士
会计从业资格考试会计证) | 经济师 | 会计职称 | 注册会计师 | 审计师 | 注册税务师
注册资产评估师 | 高级会计师 | ACCA | 统计师 | 精算师 | 理财规划师 | 国际内审师
一级建造师 | 二级建造师 | 造价工程师 | 造价员 | 咨询工程师 | 监理工程师 | 安全工程师
质量工程师 | 物业管理师 | 招标师 | 结构工程师 | 建筑师 | 房地产估价师 | 土地估价师 | 岩土师
设备监理师 | 房地产经纪人 | 投资项目管理师 | 土地登记代理人 | 环境影响评价师 | 环保工程师
城市规划师 | 公路监理师 | 公路造价师 | 安全评价师 | 电气工程师 | 注册测绘师 | 注册计量师
缤纷校园 | 实用文档 | 英语学习 | 作文大全 | 求职招聘 | 论文下载 | 访谈 | 游戏
您现在的位置: 考试吧(Exam8.com) > 计算机等级考试 > 计算机二级 > Delphi > 复习资料 > 正文

2011等考Delphi:开发Delphi对象式数据管理功能

来源:考试吧Exam8.com) 2010-10-30 9:21:41 考试吧:中国教育培训第一门户 模拟考场
在本章中将介绍Stream对象和Filer对象的实现原理、应用方法以及在超媒体系统中的应用。这对于运用Delphi 开发高级应用是很重要的。

  Read方法使用了BDE API的DbiGetBlob函数从FDataSet中读取数据,在本函数中,各参数的含义是这样的:FDataSet.Handle代表DataSet的BDE句柄,FReacord表示BLOB字段所在记录,FFieldNo表示BLOB字段号,FPosition表示要读的的数据的起始位置,Count表示要读的字节数,Buffer是读出数据所占的内存,Result是实际读出的字节数。该BDE函数返回函数调用的错误状态信息。

  Read方法还调用了NativeToAnsiBuf进行字符集的转换。

  function TBlobStream.Write(const Buffer; Count: Longint): Longint;

  var

  Temp: Pointer;

  begin

  Result := 0;

  if FOpened then

  begin

  if FField.FTransliterate then

  begin

  GetMem(Temp, Count);

  try

  AnsiToNativeBuf(FDataSet.Locale, @Buffer, Temp, Count);

  Check(DbiPutBlob(FDataSet.Handle, FRecord, FFieldNo, FPosition,

  Count, Temp));

  finally

  FreeMem(Temp, Count);

  end;

  end else

  Check(DbiPutBlob(FDataSet.Handle, FRecord, FFieldNo, FPosition,

  Count, @Buffer));

  Inc(FPosition, Count);

  Result := Count;

  FModified := True;

  end;

  end;

  Write方法调用了BDE API的DbiPutBlob函数实现往数据库BLOB字段存储数据。

  该函数的各参数含义如下:

  表20.2 调用函数DbiPutBlob的各传入参数的含义

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  参数名 含义

  ──────────────────────────────

  FDataSetHandle 写入的数据库的BDE句柄

  FRecord 写入数据的BLOB字段所在的记录

  FFieldNo BLOB字段号

  FPosition 写入的起始位置

  Count 写入的数据的字节数

  Buffer 所写入的数据占有的内存地址

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  方法中还根据FField和FTransliterate的值判断是否进行相应的字符集转换,最后移动BLOB流的位置指针,并将修改标志FModified置为True。

  3. Seek和GetBlobSize方法的实现

  Seek方法的功能主要是移动BLOB流的位置指针。GetBlobSize方法是私有的,在Seek方法中被调用,其功能是得到BLOB数据的大小。它们的实现如下:

  function TBlobStream.GetBlobSize: Longint;

  begin

  Result := 0;

  if FOpened then

  Check(DbiGetBlobSize(FDataSet.Handle, FRecord, FFieldNo, Result));

  end;

  function TBlobStream.Seek(Offset: Longint; Origin: Word): Longint;

  begin

  case Origin of

  0: FPosition := Offset;

  1: Inc(FPosition, Offset);

  2: FPosition := GetBlobSize + Offset;

  end;

  Result := FPosition;

  end;

  GetBlobSize调用了BDE API的DbiGetBlobSize函数,该函数的参数的含义同前面的API函数相同。

  4. Truncate方法

  该方法是通过调用BDE API函数实现的。其实现如下:

  procedure TBlobStream.Truncate;

  begin

  if FOpened then

  begin

  Check(DbiTruncateBlob(FDataSet.Handle, FRecord, FFieldNo, FPosition));

  FModified := True;

  end;

  end;

  该方法从BLOB流的当前位置起删除所有数据,并设置修改标志FModified为True。在Delphi VCL中许多部件特别是数据库应用方面的部件都用BDE API函数完成对数据库的访问,如Data Access和Data Control部件。各种数据库部件都是BDE API函数外层的包装简化了对数据库的访问操作。BDE API中还提供了避开BDE配置工具在程序中直接处理Alias(建立、修改、删除等)的函数支持,这也是部件所没有提供的。在Delphi数据库应用安装程序中,这些Alias操作函数无疑是相当重要的。有关BDE API函数的详细介绍,可阅读Delphi2.0 Client/Server Suite所带的BDE API 帮助文件。

  20.2 读写对象的实现原理和应用

  读写对象(Filer)包括TFiler对象、TReader对象和TWriter对象。TFiler对象是文件读写的基础对象,在应用程序中使用的主要是TReader和TWriter。TReader和TWriter对象都直接从TFiler对象继承。TFiler对象定义了Filer对象的基本属性和方法。

  Filer对象主要完成两大功能:

  ● 存取窗体文件和窗体文件中的部件

  ● 提供数据缓冲,加快数据读写操作

  20.2.1 TFiler对象

  TFiler对象是TReader和TWriter的抽象类,定义了用于部件存储的基本属性和方法。它定义了Root属性,Root指明了所读或写的部件的根对象,它的Create方法将Stream对象作为传入参数以建立与Stream对象的联系, Filer对象的具体读写操作都是由Stream对象完成。因此,只要是Stream对象所能访问的媒介都能由Filer对象存取部件。TFiler 对象还提供了两个定义属性的方法:DefineProperty和DefineBinaryProperty,这两个方法使对象能读写不在部件published部分定义的属性。

  因为Filer对象主要用于存取Delphi的窗体文件和窗体文件中的部件,所以要清楚地理解Filer对象就要清楚Delphi 窗体文件(DFM文件)的结构。

  DFM文件是用于Delphi存储窗体的。窗体是Delphi可视化程序设计的核心。窗体对应Delphi应用程序中的窗口,窗体中的可视部件对应窗口中的界面元素,非可视部件如TTable和TOpenDialog,对应Delphi应用程序的某项功能。Delphi应用程序的设计实际上是以窗体的设计为中心。因此,DFM文件在Delphi应用设计中也占很重要的位置。窗体中的所有元素包括窗体自身的属性都包含在DFM文件中。

  在Delphi应用程序窗口,界面元素是按拥有关系相互联系的,因此树状结构是最自然的表达形式;相应地,窗体中的部件也是按树状结构组织;对应在DFM文件中,也要表达这种关系。DFM文件在物理上,是以二进制方式存储的,在逻辑上则是以树状结构安排各部件的关系。Delphi编辑窗口支持以文本方式显示DFM文件。从该文本中可以看清窗体的树状结构。下面是DFM文件的文本显示:

  Object Form1: TForm1

  Left = 72

  Top = 77

  ActiveControl = DBIMage1

  …

  Object Panell: TPanel

  Left = 6

  …

  Object DBLabel1: TDBText

  …

  end

  Object DBImage1: TDBImage

  …

  end

  end

  Object Panel2: TPanel

  Left = 6

  …

  Object Label1: TLable

  …

  end

  end

  Object Panel3: TPanel

  Left = 6

  …

  Object DBLabel2: TDBText

  …

  end

  end

  end

  关于DFM文件中存储属性值的规则,请参见自定义部件开发这一章。

  对照TFiler对象的属性。Root属性就表示部件树的根──窗体。Filer对象的许多方法都是读从根起始的树中所有的部件。Ancestor属性表示根的祖先对象,IgnoreChildren属性则是读部件时忽略根的子结点。

  下面介绍Filer对象的属性和方法。

  20.2.1.1 TFiler对象的属性和方法

  1. Root属性

  声明:property Root: TComponent;

  Root 属性给Filer对象指出被读写的对象中哪一个对象是根或主要拥有者。RootComponent和WriteRootComponent方法在读和写部件及其拥有的部件前先设置Root的值。

  2. Ancestor属性

  声明:property Ancestor: TPersistent;

  Ancestor属性用于往继承下来的窗体中写部件,因为当写部件时,Write对象只需要写入与所继承的部件不同的属性,所以在写之前要跟踪每个继承的部件,并且比较它们的属性。

  如果Ancestor为nil,就表示没有相应的继承的部件,Writer对象应当将部件完全写入流。Ancestor一般为nil,只有当调用WriteDescendant和WriteDescendantRes时,才给赋值。当编写和覆盖DefineProperties时,必须设置Ancestor的值。

  3. IgnoreChildren属性

  声明:property Ignorechildren: Boolean;

  IgnoreChildren属性使一个Writer对象存储部件时可以不存储该部件拥有的部件。如果IgnoreChildren属性为True,则Writer对象存储部件不存它拥有的子部件。否则,Writer对象将所有其拥有的对象写入流。

  4. Create方法

  声明:constructor Create(Stream: TStream; BufSize: Cardinal);

  Create方法创建一个新的Filer对象,建立它和流Stream的联系;并且给它分配一个缓冲区Buffer。Buffer的大小由BufSize指定。

  5. Defineproperty方法

  声明:procedure Defineproperty(const Name: String; ReadData: TReaderProc;

  WriteData: TWriterProc; HasData: Boolean); virtual; abstract;

  Defineproperty方法定义Filer对象将作为属性存储的数据。Name参数描述接受的属性名,该属性不在published部分定义。ReadData和WriteData参数指定在存取对象时读和写所需数据的方法。HasData参数在运行时决定了属性是否有数据要存储。

  只有当对象有数据要存储时,才在该对象的DefineProperties中调用DefineProperty。DefineProperties有一个Filer对象作为它的参数,调用的就是该Filer对象的DefineProperty和DefineBinaryProperty方法。当定义属性时,Writer对象应当引用Ancestor属性,如果该属性非空,Writer对象应当只写入与从Ancestor继承的不同的属性的值。

  一个最简单的例子是TComponent的DefineProperties方法。尽管TComponent 没有在published中定义Left、Top属性,但该方法存储了部件的位置信息。

  procedure TComponent.DefineProperties(Filer: TFiler);

  begin

  Filer.DefineProperty('Left', ReadLeft, WriteLeft, LongRec(FDesignInfo).Lo <> 0);

  Filer.DefineProperty('Top', ReadTop, WriteTop, LongRec(FDesignInfo).Hi <> 0);

  end;

  6. DefineBinaryproperty方法

  声明:procedure DefineBinaryproperty(const Name: String;

  ReadData, WriteData: TStreamProc;

  HisData: Boolean); virtual; abstract;

  DefineBinaryProperty方法定义Filer对象作为属性存储的二进制数据。Name参数描述属性名。ReadData和WriteData参数描述所存储的对象中读写所需数据的方法。HasData参数在运行时决定属性是否有数据要存。

  DefineBinaryProperty和DefineProperty方法的不同之处在于,二进制型的属性直接用Stream对象读写,而不是通过Filer对象。通过ReadData和WriteData传入的方法,直接将对象数据写入流或从流读出。

  DefineBinaryProperty属性用得较少。只有标准的VCL对象定义了象图形、图像之类的二进制属性的部件中才用它。

  7. FlushBuffer方法

  声明:procedure FlushBuffer; virtual: abstract;

  FlushBuffer方法用于使Filer对象的缓冲区与相联的Stream对象同步。对Reader对象来说,是通过重新分配缓冲区;对于Writer对象是通过写入当前缓冲区。

  FlushBuffer是一个抽象方法,TReader和TWriter都覆盖了它,提供了具体实现。

  20.2.1.2 TFiler对象的实现原理

  TFiler对象是Filer对象的基础类,它定义的大多数方法都是抽象类型的,没有具体实现它,这些方法要在TReader和TWrite中覆盖。但它们提供了Filer对象的框架,了解它无疑是很重要的。

  1. TFiler对象属性的实现

  TFiler对象定义了三个属性:Root、Ancestor和IgnoreChildren。正如定义对象属性通常所采用的方法那样,要在private部分定义存储属性值的数据域,然后在public或Published部分定义该属性,并按需要增加读写控制。它们的定义如下:

  TFiler = class(TObject)

  private

  …

  FRoot: TComponent;

  FAncestor: TPersistent;

  FIgnoreChildren: Boolean;

  public

  …

  property Root: TComponent read FRoot write FRoot;

  property Ancestor: TPersistent read FAncestor write FAncestor;

  property IgnoreChildren: Boolean read FIgnoreChildren write FIgnoreChildren;

  end;

  它们在读写控制上都是直接读写私有的数据域。

  在介绍TReader和TWriter的实现,我们还会看到这几个属性的原理介绍。

  2. TFiler对象方法的实现

  在TFiler对象定义的众多方法中很多都是抽象类方法,没有具体实现。在TFiler 的后继对象TReader中覆盖了这些方法。在后面章节,会介绍这些方法的实现。

  在TFiler对象中有具体实现的有两个方法Create和Destroy。

  ⑴ Create方法的实现

  Create方法是TFiler的构造方法,它有两个参数Stream和BufSize。Stream是指定与TFiler对象相联系的Stream对象,Filer对象都是用Stream对象完成具体的读写。BufSize是TFiler对象内部开设的缓冲区的大小。Filer对象内部开设缓冲区是为了加快数据的读写,它的实现如下:

  constructor TFiler.Create(Stream: TStream; BufSize: Integer);

  begin

  FStream := Stream;

  GetMem(FBuffer, BufSize);

  FBufSize := BufSize;

  end;

  FStream、FBuffer和FBufSize都是TFiler在private部分定义的数据域。FStream表示与Filer对象相联的Stream对象,FBuffer指向Filer对象内部开设的缓冲区,FBufSize是内部缓冲区的大小。Create方法用Stream参数值给FStream赋值,然后用GetMem分配BufSize大小的动态内存作为内部缓冲区。

  ⑵ Destroy方法的实现

  Destroy方法是TFiler对象的析构函数,它的作用就是释放动态内存。

  destructor TFiler.Destroy;

  begin

  if FBuffer <> nil then FreeMem(FBuffer, FBufSize);

  end;

  20.2.2 TWriter对象

  TWriter 对象是可实例化的,往流中写数据的Filer对象。TWriter对象直接从TFiler继承而来,除了覆盖从TFiler继承的方法外,还增加了大量的关于写各种数据类型(如Integer、String和Component等)的方法。TWriter对象和TReader 对象配合使用将使对象读写发挥巨大作用。

  20.2.2.1 TWriter对象的属性和方法

  1. Position属性

  声明:property Position: Longint;

  TWriter对象的Position属性表示相关联的流中的当前要写的位置,TReader 对象也有这个属性,但与TReader对象不同的是TWriter对象的Position的值比流的Position值小,这一点一看属性实现就清楚了。

  2. RootAncesstor属性

  声明:property RootAncestor: TComponent;

  RootAncestor属性表示的是Root属性所指的部件的祖先。如果Root 是继承的窗体,Writer对象将窗体拥有部件与祖先窗体中的相应部件依次比较,然后只写入那些与祖先中的不同的部件。

  3. Write方法

  声明:procedure Write(const Buf; Count: Longint);

  Write方法从Buf中往与Writer相关联的流中写入Count个字节。

  4. WriteListBegin方法

  声明:procedure WriteListBegin;

  WriteListBegin方法往Write对象的流中写入项目列表开始标志,该标志意味着后面存储有一连串的项目。Reader对象,在读这一连串项目时先调用ReadListBegin方法读取该标志位,然后用EndOfList判断是否列表结束,并用循环语句读取项目。在调用WriteListBegin方法的后面必须调用WriteListEnd方法写列表结束标志,相应的在Reader对象中有ReadListEnd方法读取该结束标志。

  5. WriteListEnd方法

  声明:procedure WriteListEnd;

  WriteListEnd方法在流中,写入项目列表结束标志,它是与WriteListBegin相匹配的方法。

  6. WriteBoolean方法

  声明:procedure WriteBoolean(Value: Boolean);

  WriteBoolean方法将Value传入的布尔值写入流中。

  7. WriteChar方法

  声明:procedure WriteChar(Value: char);

  WriteChar方法将Value中的字符写入流中。

  8. WriteFloat方法

  声明:procedure WriteFloat(Value: Extended);

  WriteFloat方法将Value传入的浮点数写入流中。

  9. WriteInteger方法

  声明:procedure WriteInteger(Value: Longint);

  WriteInteger方法将Value中的整数写入流中。

  10. WriteString方法

  声明:procedure WriteString(const Value: string);

  WriteString方法将Value中的字符串写入流中。

  11. WriteIdent方法

  声明:procedure WriteIdent(const Ident: string);

  WriteIdent方法将Ident传入的标识符写入流中。

上一页  1 2 3 4 5 6 7 8 9 下一页
  相关推荐:2010年9月计算机等级考试试题及答案解析专题
       预告:名师解析2010年9月计算机等级考试试题答案
       2010年9月计算机等级考试成绩查询时间及入口
       2010年9月计算机等考成绩查询短信免费提醒开通
文章搜索
版权声明:如果计算机等级考试网所转载内容不慎侵犯了您的权益,请与我们联系800@exam8.com,我们将会及时处理。如转载本计算机等级考试网内容,请注明出处。