版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、20.2.1.1 TFiler对象的属性和方法1. Root属性声明:property Root: TComponent;Root 属性给Filer对象指出被读写的对象中哪一个对象是根或主要拥有者。RootCompone nt和WriteRootComponent方法在读和写部件及其拥有的部件前先设置Root的值。2. Ancestor属性声明:property Ancestor: TPersistent;Ancestor属性用于往继承下来的窗体中写部件,因为当写部件时,Write对象只需要写入与所继承的部件不同的属性,所以在写之前要跟踪每个继承的部件,并且比较它们的属性。如果Ancestor
2、为nil,就表示没有相应的继承的部件,Writer对象应当将部件完全写入流。Ancestor一般为nil,只有当调用WriteDescendant和WriteDescendantRes时,才给赋值。当编写和覆盖DefineProperties时,必须设置Ancestor的值。3. IgnoreChildren属性声明:property Ignorechildren: Boolean;IgnoreChildren属性使一个Writer对象存储部件时可以不存储该部件拥有的部件。如果Ign oreChildren属性为True,则Writer对象存储部件不存它拥有的子部件。否则,Writer对象将所
3、有其拥有的对象写入流。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; abstra
4、ct;Defineproperty方法定义Filer对象将作为属性存储的数据。Name参数描述接受的属性名,该属性不在published部分定义。ReadData和WriteData参数指定在存取对象时读和写所需数据的方法。HasData参数在运行时决定了属性是否有数据要存储。只有当对象有数据要存储时,才在该对象的DefineProperties中调用DefineProperty。DefineProperties有一个Filer对象作为它的参数,调用的就是该Filer对象的DefineProper ty和DefineBinaryProperty方法。当定义属性时,Writer对象应当引用Anc
5、estor属性,如果该属性非空,Writer对象应当只写入与从Ancestor继承的不同的属性的值。一个最简单的例子是TComponent的DefineProperties方法。尽管TComponent 没有在published中定义Left、Top属性,但该方法存储了部件的位置信息。procedure TComponent.DefineProperties(Filer: TFiler;beginFiler.DefineProperty(Left, ReadLeft, WriteLeft, LongRec(FDesignInfo.Lo 0; Filer.DefineProperty(Top,
6、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参数
7、在运行时决定属性是否有数据要存。DefineBinaryProperty和DefineProperty方法的不同之处在于,二进制型的属性直接用Stream对象读写,而不是通过Filer对象。通过ReadData和WriteData传入的方法,直接将对象数据写入流或从流读出。DefineBinaryProperty属性用得较少。只有标准的VCL对象定义了象图形、图像之类的二进制属性的部件中才用它。7. FlushBuffer方法声明:procedure FlushBuffer; virtual: abstract;FlushBuffer方法用于使Filer对象的缓冲区与相联的Stream对象同步
8、。对Reader对象来说,是通过重新分配缓冲区;对于Writer对象是通过写入当前缓冲区。FlushBuffer是一个抽象方法,TReader和TWriter都覆盖了它,提供了具体实现。20.2.1.2 TFiler对象的实现原理TFiler对象是Filer对象的基础类,它定义的大多数方法都是抽象类型的,没有具体实现它,这些方法要在TReader和TWrite中覆盖。但它们提供了Filer对象的框架,了解它无疑是很重要的。1. TFiler对象属性的实现TFiler对象定义了三个属性:Root、Ancestor和IgnoreChildren。正如定义对象属性通常所采用的方法那样,要在priva
9、te部分定义存储属性值的数据域,然后在public或Publis hed部分定义该属性,并按需要增加读写控制。它们的定义如下:TFiler = class(TObjectprivateFRoot: TComponent;FAncestor: TPersistent;FIgnoreChildren: Boolean;publicproperty Root: TComponent read FRoot write FRoot;property Ancestor: TPersistent read FAncestor write FAncestor;property IgnoreChildren:
10、Boolean read FIgnoreChildren write FIgnoreChildren;end;它们在读写控制上都是直接读写私有的数据域。在介绍TReader和TWriter的实现,我们还会看到这几个属性的原理介绍。2. TFiler对象方法的实现在TFiler对象定义的众多方法中很多都是抽象类方法,没有具体实现。在TFiler 的后继对象TReader中覆盖了这些方法。在后面章节,会介绍这些方法的实现。在TFiler对象中有具体实现的有两个方法Create和Destroy。Create方法的实现Create方法是TFiler的构造方法,它有两个参数Stream和BufSize。
11、Stream是指定与TFiler对象相联系的Stream对象,Filer对象都是用Stream对象完成具体的读写。Buf Size是TFiler对象内部开设的缓冲区的大小。Filer对象内部开设缓冲区是为了加快数据的读写,它的实现如下:constructor TFiler.Create(Stream: TStream; BufSize: Integer;beginFStream := Stream;GetMem(FBuffer, BufSize;FBufSize := BufSize;end;FStream、FBuffer和FBufSize都是TFiler在private部分定义的数据域。FS
12、tream表示与Filer对象相联的Stream对象,FBuffer指向Filer对象内部开设的缓冲区,FBufSize 是内部缓冲区的大小。Create方法用Stream参数值给FStream赋值,然后用GetMem分配BufSize大小的动态内存作为内部缓冲区。Destroy方法的实现Destroy方法是TFiler对象的析构函数,它的作用就是释放动态内存。destructor TFiler.Destroy;beginif FBuffer nil then FreeMem(FBuffer, FBufSize;end;20.2.2 TWriter对象TWriter 对象是可实例化的,往流中写
13、数据的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的值比流的Posit
14、ion值小,这一点一看属性实现就清楚了。2. RootAncesstor属性声明:property RootAncestor: TComponent;RootAncestor属性表示的是Root属性所指的部件的祖先。如果Root 是继承的窗体,Writ er对象将窗体拥有部件与祖先窗体中的相应部件依次比较,然后只写入那些与祖先中的不同的部件。3. Write方法声明:procedure Write(const Buf; Count: Longint;Write方法从Buf中往与Writer相关联的流中写入Count个字节。4. WriteListBegin方法声明:procedure Writ
15、eListBegin;WriteListBegin方法往Write对象的流中写入项目列表开始标志,该标志意味着后面存储有一连串的项目。Reader对象,在读这一连串项目时先调用ReadListBegin方法读取该标志位,然后用EndOfList判断是否列表结束,并用循环语句读取项目。在调用WriteListBegin 方法的后面必须调用WriteListEnd方法写列表结束标志,相应的在Reader对象中有Read ListEnd方法读取该结束标志。5. WriteListEnd方法声明:procedure WriteListEnd;WriteListEnd方法在流中,写入项目列表结束标志,它
16、是与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
17、 WriteInteger(Value: Longint;WriteInteger方法将Value中的整数写入流中。10. WriteString方法声明:procedure WriteString(const Value: string;WriteString方法将Value中的字符串写入流中。11. WriteIdent方法声明:procedure WriteIdent(const Ident: string;WriteIdent方法将Ident传入的标识符写入流中。12. WriteSignature方法声明:procedure WriteSignature;WriteSignature
18、方法将Delphi Filer对象标签写入流中。WriteRootComponent方法在将部件写入流之前先调用WriteSignature方法写入Filer标签。Reader对象在读部件之前调用R eadSignature方法读取该标签以指导读操作。13. WritComponent方法声明:procedure WriteComponent(Component: TComponent;WriteComponent方法调用参数Component的WriteState方法将部件写入流中。在调用W riteState之前,WriteComponent还将Component的ComponetnSta
19、te属性置为csWriting。当WriteState返回时再清除csWriting.14. WriteRootComponent方法声明:procedure WriteRootComponent(Root: TComponent;WriteRootComponent方法将Writer对象Root属性设为参数Root带的值,然后调用Writ eSignature方法往流中写入Filer对象标签,最后调用WriteComponent方法在流中存储R oot部件。20.2.2.2 TWriter对象的实现TWriter对象提供了许多往流中写各种类型数据的方法,这对于程序员来说是很重要的功能。TWr
20、ite对象往流中写数据是依据不同的数据采取不同的格式的。因此要掌握TWrit er对象的实现和应用方法,必须了解Writer对象存储数据的格式。首先要说明的是,每个Filer对象的流中都包含有Filer对象标签。该标签占四个字节其值为“TPF0”。Filer对象为WriteSignature和ReadSignature方法存取该标签。该标签主要用于Reader对象读数据(部件等时,指导读操作。其次,Writer对象在存储数据前都要留一个字节的标志位,以指出后面存放的是什么类型的数据。该字节为TValueType类型的值。TValueType是枚举类型,占一个字节空间,其定义如下:TValueT
21、ype = (VaNull, VaList, VaInt8, VaInt16, VaInt32, VaEntended, VaString, VaIdent,VaFalse, VaTrue, VaBinary, VaSet, VaLString, VaNil, VaCollection;因此,对Writer对象的每一个写数据方法,在实现上,都要先写标志位再写相应的数据;而Reader对象的每一个读数据方法都要先读标志位进行判断,如果符合就读数据,否则产生一个读数据无效的异常事件。VaList标志有着特殊的用途,它是用来标识后面将有一连串类型相同的项目,而标识连续项目结束的标志是VaNull。因
22、此,在Writer对象写连续若干个相同项目时,先用WriteListBegin写入VaList标志,写完数据项目后,再写出VaNull标志;而读这些数据时,以ReadListBegin开始,ReadListEnd结束,中间用EndofList函数判断是否有VaNull标志。下面就介绍它们的实现。1. TWriter对象属性的实现TWriter对象直接从TFiler对象继承,它只增加了Position和RootAncestor属性。RootAncestor属性在private部分有数据域FRootAncestor存入其值。在属性定义的读与控制上都是直接读取该值。Position属性的定义中包含了
23、两个读写控制方法:GetPosition和SetPosition:TWriter = class(TFilerprivateFRootAncestor: TComponent;function GetPosition: Longint;procedure SetPosition(Value: Longint;publicproperty Position: Longint read GetPosition write SetPosition;property RootAncestor: TComponent read FRootAncestor write FRootAncestor; end
24、;GetPosition和SetPosition方法实现如下:function TWriter.GetPosition: Longint;beginResult := FStream.Position + FBufPos;end;procedure TWriter.SetPosition(Value: Longint;varStreamPosition: Longint;beginStreamPosition := FStream.Position; 只清除越界的缓冲区if (Value StreamPosition + FBufPos then beginWriteBuffer;FStrea
25、m.Position := Value;endelse FBufPos := Value - StreamPosition;end;WriteBuffer是TWriter对象定义的私有方法,它的作用是将Writer 对象内部缓冲区中的有效数据写入流中,并将FBufPos置为0。Writer对象的FlushBuffer对象就是用Write Buffer方法刷新缓冲区。在SetPosition方法中,如果Value值超出了边界(FStream.Position,FStream.Positi on + FBufPos,就将缓冲区中的内容写入流,重新设置缓冲区在流中的相对位置;否则,就只是移动FBuf
26、Pos指针。2. TWriter方法的实现WriteListBegin和WriteListEnd的实现这两个方法都是用于写连续若干个相同类型的值。WriteListBegin写入VaList标志,W riteListEnd写入VaNull标志。procedure TWriter.WriteListBegin;beginWriteValue(vaList;end;procedure TWriter.WriteListEnd;beginWriteValue(vaNull;end;这两个方法都调用TWriter对象的WriteValue方法,该方法主要用于写入TValueType 类型的值。proc
27、edure TWriter.WriteValue(Value: TValueType;beginWrite(Value, SizeOf(Value;end;简单数据类型的写入简单数据类型指的是整型、字符型、字符串型、浮点型、布尔型等。TWriter对象都定义了相应的写入方法。WriteInteger方法用于写入整型数据。procedure TWriter.WriteInteger(Value: Longint;beginif (Value = -128 and (Value = -32768 and (Value = 32767 thenbeginWriteValue(vaInt16;Writ
28、e(Value, SizeOf(Smallint;end elsebeginWriteValue(vaInt32;Write(Value, SizeOf(Longint;end;end;WriteInteger方法将整型数据分为8位、16位和32位三种,并分别用vaInt8、vaInt1 6和VaInt32。WriteBoolean用于写入布尔型数据:procedure TWriter.WriteBoolean(Value: Boolean;beginif Value thenWriteValue(vaTrue elseWriteValue(vaFalse;end;与其它数据类型不同的是布尔型
29、数据只使用了标志位是存储布尔值,在标志位后没有数据。WriteFloat方法用于写入浮点型数据。procedure TWriter.WriteFloat(Value: Extended;beginWriteValue(vaExtended;Write(Value, SizeOf(Extended;end;字符串“True”、“False”和“nil”作为标识符传入是由于Delphi的特殊需要。如果是“True”、“False”和“nil”则写入VaTrue、VaFalse和VaNil,否则写入VaIdent标志,接着以字符串形式写入标识符。WriteString方法用于写入字符串procedu
30、re TWriter.WriteString(const Value: string;varL: Integer;beginL := Length(Value;if L = 255 thenbeginWriteValue(vaString;Write(L, SizeOf(Byte;end elsebeginWriteValue(vaLString;Write(L, SizeOf(Integer;end;Write(Pointer(Value, L;end;Delphi的字符串类型有两种。一种长度小于256个字节,另一种长度小于65536 个字节。WriteString方法区分这两类情况存储字符
31、串,一种设置VaStirng标志,另一种设置V aLString。然后存储字符串的长度值,最后存储字符串数据。WriteChar方法用于写入字符。procedure TWriter.WriteChar(Value: Char;beginWriteString(Value;end;字符类型的读写是用读写字符串的方法,在读的时候,判断字节数为1时,则为字符型。部件的写入TWriter对象中与写入部件有关的方法有WriteSignature、WritePrefix、WriteCompon ent、WriteDescendant和WriteRootComponent。WriteSignature方法用
32、于往流中写入Filer对象标签。procedure TWriter.WriteSignature;beginWrite(FilerSignature, SizeOf(FilerSignature;end;FilerStgnature是字符串常量,其值为“TPF0”,代表对象标签。WritePrefix方法用于在写入部件前写入ffInherited和ffChildPos标志,这些标志表示部件的继承特征和创建序值特征。procedure TWriter.WritePrefix(Flags: TFilerFlags; AChildPos: Integer;varPrefix: Byte;beginif Flags thenbeginPrefix := $F0 or Byte(Flags;Write(Pref
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论