首页 考试吧论坛 Exam8视线 考试商城 网络课程 模拟考试 考友录 实用文档 求职招聘 论文下载 | ||
2011中考 | 2011高考 | 2012考研 | 考研培训 | 在职研 | 自学考试 | 成人高考 | 法律硕士 | MBA考试 MPA考试 | 中科院 |
||
四六级 | 职称英语 | 商务英语 | 公共英语 | 托福 | 雅思 | 专四专八 | 口译笔译 | 博思 | GRE GMAT 新概念英语 | 成人英语三级 | 申硕英语 | 攻硕英语 | 职称日语 | 日语学习 | 法语 | 德语 | 韩语 |
||
计算机等级考试 | 软件水平考试 | 职称计算机 | 微软认证 | 思科认证 | Oracle认证 | Linux认证 华为认证 | Java认证 |
||
公务员 | 报关员 | 银行从业资格 | 证券从业资格 | 期货从业资格 | 司法考试 | 法律顾问 | 导游资格 报检员 | 教师资格 | 社会工作者 | 外销员 | 国际商务师 | 跟单员 | 单证员 | 物流师 | 价格鉴证师 人力资源 | 管理咨询师考试 | 秘书资格 | 心理咨询师考试 | 出版专业资格 | 广告师职业水平 驾驶员 | 网络编辑 |
||
卫生资格 | 执业医师 | 执业药师 | 执业护士 | ||
会计从业资格考试(会计证) | 经济师 | 会计职称 | 注册会计师 | 审计师 | 注册税务师 注册资产评估师 | 高级会计师 | ACCA | 统计师 | 精算师 | 理财规划师 | 国际内审师 |
||
一级建造师 | 二级建造师 | 造价工程师 | 造价员 | 咨询工程师 | 监理工程师 | 安全工程师 质量工程师 | 物业管理师 | 招标师 | 结构工程师 | 建筑师 | 房地产估价师 | 土地估价师 | 岩土师 设备监理师 | 房地产经纪人 | 投资项目管理师 | 土地登记代理人 | 环境影响评价师 | 环保工程师 城市规划师 | 公路监理师 | 公路造价师 | 安全评价师 | 电气工程师 | 注册测绘师 | 注册计量师 |
||
缤纷校园 | 实用文档 | 英语学习 | 作文大全 | 求职招聘 | 论文下载 | 访谈 | 游戏 |
12. WriteSignature方法
声明:procedure WriteSignature;
WriteSignature方法将Delphi Filer对象标签写入流中。WriteRootComponent方法在将部件写入流之前先调用WriteSignature方法写入Filer标签。Reader对象在读部件之前调用ReadSignature方法读取该标签以指导读操作。
13. WritComponent方法
声明:procedure WriteComponent(Component: TComponent);
WriteComponent方法调用参数Component的WriteState方法将部件写入流中。在调用WriteState之前,WriteComponent还将Component的ComponetnState属性置为csWriting。当WriteState返回时再清除csWriting.
14. WriteRootComponent方法
声明:procedure WriteRootComponent(Root: TComponent);
WriteRootComponent方法将Writer对象Root属性设为参数Root带的值,然后调用WriteSignature方法往流中写入Filer对象标签,最后调用WriteComponent方法在流中存储Root部件。
20.2.2.2 TWriter对象的实现
TWriter对象提供了许多往流中写各种类型数据的方法,这对于程序员来说是很重要的功能。TWrite对象往流中写数据是依据不同的数据采取不同的格式的。 因此要掌握TWriter对象的实现和应用方法,必须了解Writer对象存储数据的格式。
首先要说明的是,每个Filer对象的流中都包含有Filer对象标签。该标签占四个字节其值为“TPF0”。Filer对象为WriteSignature和ReadSignature方法存取该标签。该标签主要用于Reader对象读数据(部件等)时,指导读操作。
其次,Writer对象在存储数据前都要留一个字节的标志位,以指出后面存放的是什么类型的数据。该字节为TValueType类型的值。TValueType是枚举类型,占一个字节空间,其定义如下:
TValueType = (VaNull, VaList, VaInt8, VaInt16, VaInt32, VaEntended, VaString, VaIdent,
VaFalse, VaTrue, VaBinary, VaSet, VaLString, VaNil, VaCollection);
因此,对Writer对象的每一个写数据方法,在实现上,都要先写标志位再写相应的数据;而Reader对象的每一个读数据方法都要先读标志位进行判断,如果符合就读数据,否则产生一个读数据无效的异常事件。VaList标志有着特殊的用途,它是用来标识后面将有一连串类型相同的项目,而标识连续项目结束的标志是VaNull。因此,在Writer对象写连续若干个相同项目时,先用WriteListBegin写入VaList标志,写完数据项目后,再写出VaNull标志;而读这些数据时,以ReadListBegin开始,ReadListEnd结束,中间用EndofList函数判断是否有VaNull标志。
下面就介绍它们的实现。
1. TWriter对象属性的实现
TWriter对象直接从TFiler对象继承,它只增加了Position和RootAncestor属性。
RootAncestor属性在private部分有数据域FRootAncestor存入其值。在属性定义的读与控制上都是直接读取该值。
Position属性的定义中包含了两个读写控制方法:GetPosition和SetPosition:
TWriter = class(TFiler)
private
FRootAncestor: TComponent;
…
function GetPosition: Longint;
procedure SetPosition(Value: Longint);
public
…
property Position: Longint read GetPosition write SetPosition;
property RootAncestor: TComponent read FRootAncestor write FRootAncestor;
end;
GetPosition和SetPosition方法实现如下:
function TWriter.GetPosition: Longint;
begin
Result := FStream.Position + FBufPos;
end;
procedure TWriter.SetPosition(Value: Longint);
var
StreamPosition: Longint;
begin
StreamPosition := FStream.Position;
{ 只清除越界的缓冲区 }
if (Value < StreamPosition) or (Value > StreamPosition + FBufPos) then
begin
WriteBuffer;
FStream.Position := Value;
end
else FBufPos := Value - StreamPosition;
end;
WriteBuffer是TWriter对象定义的私有方法,它的作用是将Writer 对象内部缓冲区中的有效数据写入流中,并将FBufPos置为0。Writer对象的FlushBuffer对象就是用WriteBuffer方法刷新缓冲区。
在SetPosition方法中,如果Value值超出了边界(FStream.Position,FStream.Position + FBufPos),就将缓冲区中的内容写入流,重新设置缓冲区在流中的相对位置;否则,就只是移动FBufPos指针。
2. TWriter方法的实现
⑴ WriteListBegin和WriteListEnd的实现
这两个方法都是用于写连续若干个相同类型的值。WriteListBegin写入VaList标志,WriteListEnd写入VaNull标志。
procedure TWriter.WriteListBegin;
begin
WriteValue(vaList);
end;
procedure TWriter.WriteListEnd;
begin
WriteValue(vaNull);
end;
这两个方法都调用TWriter对象的WriteValue方法,该方法主要用于写入TValueType类型的值。
procedure TWriter.WriteValue(Value: TValueType);
begin
Write(Value, SizeOf(Value));
end;
⑵ 简单数据类型的写入
简单数据类型指的是整型、字符型、字符串型、浮点型、布尔型等。TWriter对象都定义了相应的写入方法。
WriteInteger方法用于写入整型数据。
procedure TWriter.WriteInteger(Value: Longint);
begin
if (Value >= -128) and (Value <= 127) then
begin
WriteValue(vaInt8);
Write(Value, SizeOf(Shortint));
end else
if (Value >= -32768) and (Value <= 32767) then
begin
WriteValue(vaInt16);
Write(Value, SizeOf(Smallint));
end else
begin
WriteValue(vaInt32);
Write(Value, SizeOf(Longint));
end;
end;
WriteInteger方法将整型数据分为8位、16位和32位三种,并分别用vaInt8、vaInt16和VaInt32。
WriteBoolean用于写入布尔型数据:
procedure TWriter.WriteBoolean(Value: Boolean);
begin
if Value then
WriteValue(vaTrue) else
WriteValue(vaFalse);
end;
与其它数据类型不同的是布尔型数据只使用了标志位是存储布尔值,在标志位后没有数据。
WriteFloat方法用于写入浮点型数据。
procedure TWriter.WriteFloat(Value: Extended);
begin
WriteValue(vaExtended);
Write(Value, SizeOf(Extended));
end;
字符串“True”、“False”和“nil”作为标识符传入是由于Delphi的特殊需要。如果是“True”、“False”和“nil”则写入VaTrue、VaFalse和VaNil,否则写入VaIdent标志,接着以字符串形式写入标识符。
WriteString方法用于写入字符串
procedure TWriter.WriteString(const Value: string);
var
L: Integer;
begin
L := Length(Value);
if L <= 255 then
begin
WriteValue(vaString);
Write(L, SizeOf(Byte));
end else
begin
WriteValue(vaLString);
Write(L, SizeOf(Integer));
end;
Write(Pointer(Value)^, L);
end;
Delphi的字符串类型有两种。一种长度小于256个字节,另一种长度小于65536 个字节。WriteString方法区分这两类情况存储字符串,一种设置VaStirng标志,另一种设置VaLString。然后存储字符串的长度值,最后存储字符串数据。
WriteChar方法用于写入字符。
procedure TWriter.WriteChar(Value: Char);
begin
WriteString(Value);
end;
字符类型的读写是用读写字符串的方法,在读的时候,判断字节数为1时,则为字符型。
⑶ 部件的写入
TWriter对象中与写入部件有关的方法有WriteSignature、WritePrefix、WriteComponent、WriteDescendant和WriteRootComponent。
WriteSignature方法用于往流中写入Filer对象标签。
procedure TWriter.WriteSignature;
begin
Write(FilerSignature, SizeOf(FilerSignature));
end;
FilerStgnature是字符串常量,其值为“TPF0”,代表对象标签。
WritePrefix方法用于在写入部件前写入ffInherited和ffChildPos标志,这些标志表示部件的继承特征和创建序值特征。
procedure TWriter.WritePrefix(Flags: TFilerFlags; AChildPos: Integer);
var
Prefix: Byte;
begin
if Flags <> [] then
begin
Prefix := $F0 or Byte(Flags);
Write(Prefix, SizeOf(Prefix));
if ffChildPos in Flags then WriteInteger(AChildPos);
end;
end;
如果ffChildPos置位,则存入部件在Owner中的创建序值。更详细的信息请参阅TReader的ReadPrefix方法。
WriteComponent方法往流中写入部件。
procedure TWriter.WriteComponent(Component: TComponent);
function FindAncestor(const Name: string): TComponent;
begin
…
end;
begin
Include(Component.FComponentState, csWriting);
if Assigned(FAncestorList) then
Ancestor := FindAncestor(Component.Name);
Component.WriteState(Self);
Exclude(Component.FComponentState, csWriting);
end;
方法中用Component的WritState方法写入部件的属性。在写入之前将Component.FComponentState置为csWriting写入完后再将csWriting复位。
WriteDescendant是根据祖先AAncestor的情况写入部件Root。
procedure TWriter.WriteDescendent(Root: TComponent; AAncestor: TComponent);
begin
FRootAncestor := AAncestor;
FAncestor := AAncestor;
FRoot := Root;
WriteSignature;
WriteComponent(Root);
end;
方法先调用WriteSignature方法写入Filer对象标签。然后调用WriteComponent将部件Root写入流。
WriteRootComponent方法则是调用WriteDescendant方法写入部件,只是将后者的Ancestor参数以nil值传入。
procedure TWriter.WriteRootComponent(Root: TComponent);
begin
WriteDescendent(Root, nil);
end;
20.2.3 TReader对象
TReader对象是可实例化的用于从相联系的流中读取数据的Filer对象。TReader对象从TFiler继承下来,除了从TFiler继承的属性和方法外,TReader声明了不少属性、方法和事件。
Owner和Parent属性用于表示从Reader对象的流中读取的部件的拥有者和双亲结点。OnError,OnFindMethod和OnSetName事件使应用程序在运行中读数据时能定制响应方式。除了覆盖了一些从TFiler对象中继承的方法外,TReader对象还定义大量的读不同类型的数据和触发事件的方法。
20.2.3.1 TReader对象的属性和方法
1. Owner属性
声明:property Owner: TComponent;
Reader对象的Owner属性存储了将用来给从Reader的流中读出的部件的Owner属性赋值的部件。
2. Parent属性
声明:property Parent: TComponent;
Parent属性存储将用来给从Reader的流中读出所有控制的Parent属性赋值的部件。
3. Position属性
声明:propertion: Longint;
Reader对象的Position属性表示相联的流中读的当前位置。Position的值还应包括读缓冲区的大小。对于Reader 对象,Position的值大于流的Position 的值。如果将Position的值设得超过当前缓冲区,将引起调用FlushBuffer。
4. BeginReferences方法
声明:procedure BeginReferences;
BeginReferences方法启动一连串关于读部件的命令,这些部件包含相互间的交叉引用。在使用上通常和FixupReferences和EndReferences一起放在Try…finally程序块中。
在调用了BeginReferences后,Reader对象创建读取所有对象和名字的列表。所有的独立对象被读出后,调用FixupReferences方法将名字的相互从流中转移到对象实例中。最后调用EndReferences方法释放列表。
处理部件相互引用的程序块形式如下:
BeginReferences; { 创建临时列表 }
try
{ 读出所有部件并将它们的名字放在一临时列表中 }
…
FixupReferences; { 分 解 }
finally
EndReferences; { 释放临时列表 }
end;
5. FixUpReferences方法
声明:procedure FixupReferences;
FixupReferences方法分解从流中读出的存在各种相互依赖部件的引用关系。FixupReferences总在try…finally块中并配合BeginReferences和EndReferences一起使用。
6. EndReferences方法
声明:procedure EndReferences;
EndReferences方法终止处理相互引用的块操作,释放对象列表。它总配合BeginReferences和FixupReferences一起使用。
7. ReadListBegin方法
声明:procedure ReadListBegin;
ReadListBegin方法从Reader对象相联的流中读取列表开始标志。如果流中紧接着要读取的项目不是一个由WritelistBegin方法写入的列表起始标志,ReadListBegin将引起一个读异常事件。
通常在调用ReadlistBegin方法之后,紧跟着一个读项目的循环,循环以EndfList方法返回True 终止条件。这时,预示流中的下一个项目是列表结束标志,需要调用ReadListEnd方法。
8. ReadListEnd方法
声明:procedure ReadListEnd;
ReadListEnd 方法从流中读取列表结束标志。如果所读的项目不是一个列表结束标志,ReadListEnd方法引发一个EReadError异常事件。
9. EndOfList方法
声明:function EndOfList: Boolean;
如果Reader对象读到项目列表结果标志,EndOfList方法返回True。
TStrings对象在从Reader对象读取项目列表时使用了ReadListBegin和ReadListEnd方法。下面的ReadData是TStrings的方法,用于在DefineProperties方面中读string数据。
procedure TStrings.ReadData(Reader: TReader);
begin
Reader.ReadListBegin; { 读列表开始标志 }
Clear; { 清除已有的字符串 }
while not Reader.EndOfList do { 只要还有数据 … }
Add(Reader.ReadString); { …读一个字符串并将其加在列表中 }
Reader.ReadListEnd; { 越过列表结束标志 }
end;
10. ReadSignature方法
声明:procedure ReadSignature;
ReadSignature方法从流中读取部件之前首先调用ReadSignature方法。在载入对象之前检测标签。Reader对象就能防止疏忽大意,导致读取无效或过时的数据。Filer标签是四个字符,对于Delphi 2.0,该标签是“TPF0”。
11. ReadPrefix方法
声明:procedure ReadPrefix(var Plags: TFilerFlags; var AChild, Pos: Integer);
ReadPrefix方法的功能与ReadSignature的很相象,只不过它是读取流中部件前面的标志(PreFix)。当一个Write对象将部件写入流中时,它在部件前面预写了两个值,第一个值是指明部件是否是从祖先窗体中继承的窗体和它在窗体中的位置是否重要的标志;第二个值指明它在祖先窗体创建次序。ReadComponent方法自动调用ReadPrefix。但如果需要独立读取部件的预读标志,也可直接调用该方向。
12. OnFindMethod事件
声明:property OnFindMethod: TFindMethodEvent;
OnFindMethod事件,发生在Reader对象读取对象的方法指针时,属性为方法指针的通常都是事件。
响应OnFindMethod事件的理由,通常是处理过程找不到方法的情况。在FindMethod方法没有找到由Name指定的方法的情况下,如果它将OnFindMethod方法的Error 参数设为True,将引起ReadError异常事件;反之,将Error参数置为False,将防止FindMethod方法引发异常事件。
相关推荐:2010年9月计算机等级考试试题及答案解析专题北京 | 天津 | 上海 | 江苏 | 山东 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
广东 | 河北 | 湖南 | 广西 | 河南 |
海南 | 湖北 | 四川 | 重庆 | 云南 |
贵州 | 西藏 | 新疆 | 陕西 | 山西 |
宁夏 | 甘肃 | 青海 | 辽宁 | 吉林 |
黑龙江 | 内蒙古 |