1.TWriter对象

WriteBuffer是TWriter对象定义的私有方法,它的作用是将Writer 对象内部缓冲区中的有效数据写入流中,并将FBufPos置为0。FlushBuffer对象就是用WriteBuffer方法刷新缓冲区。

procedure TWriter.WriteBuffer;
 begin
   FStream.WriteBuffer(FBuffer^, FBufPos);
   FBufPos := 0;
 end;

 

在SetPosition方法中,如果Value值超出了边界(FStream.Position,FStream.Position + FBufPos),就将缓冲区中的内容写入流,重新设置缓冲区在流中的相对位置;否则,就只是移动FBufPos指针。

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;

 

WriteListBegin和WriteListEnd的实现,WriteListBegin写入VaList标志,WriteListEnd写入VaNull标志。 两个方法都调用TWriter对象的WriteValue方法,该方法主要用于写入TValueType类型的值。

procedure TWriter.WriteValue(Value: TValueType); 
 begin 
 Write(Value, SizeOf(Value));  
 end;procedure TWriter.WriteListBegin; 
 begin 
 WriteValue(vaList); 
 end; procedure TWriter.WriteListEnd; 
 begin 
 WriteValue(vaNull); 
 end;

简单数据类型的写入
简单数据类型指的是整型、字符型、字符串型、浮点型、布尔型等。TWriter对象都定义了相应的写入方法。
WriteInteger方法将整型数据分为8位、16位和32位三种,并分别用vaInt8、vaInt16和VaInt32。

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;

 

与其它数据类型不同的是布尔型数据只使用了标志位是存储布尔值,在标志位后没有数据。字符串“True”、“False”和“nil”作为标识符传入是由于Delphi的特殊需要。如果是“True”、“False”和“nil”则写入VaTrue、VaFalse和VaNil,否则写入VaIdent标志,接着以字符串形式写入标识符。

procedure TWriter.WriteFloat(Value: Extended);
 begin 
 WriteValue(vaExtended); 
 Write(Value, SizeOf(Extended)); 
 end;

 
WriteString方法用于写入字符串 .Delphi的字符串类型有两种。一种长度小于256个字节,另一种长度小于65536 个字节。WriteString方法区分这两类情况存储字符串,一种设置VaStirng标志,另一种设置VaLString。然后存储字符串的长度值,最后存储字符串数据。

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;


 
部件的写入:

TWriter对象中与写入部件有关的方法有WriteSignature、WritePrefix、WriteComponent、WriteDescendant和WriteRootComponent。 
procedure TWriter.WriteSignature; //WriteSignature方法用于往流中写入Filer对象标签。FilerStgnature是字符串常量,其值为“TPF0”,代表对象标签。

begin 
 Write(FilerSignature, SizeOf(FilerSignature)); 
 end;

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); //如果ffChildPos置位,则存入部件在Owner中的创建序值 end; 
 end;

WriteComponent方法往流中写入部件。

procedure TWriter.WriteComponent(Component: TComponent);
  function FindAncestor(const Name: string): TComponent;
   begin  end;
var
   OldAncestor: TPersistent;
   OldRootAncestor: TComponent;
   AncestorComponent: TComponent;
   I: Integer;
 begin
   OldAncestor := Ancestor;
   OldRootAncestor := RootAncestor;
   try
     Include(Component.FComponentState, csWriting); //将控件的FComponentState置为csWriting
     for I := 0 to Component.ComponentCount - 1 do //将其所拥有的控件的FComponentState置为csWriting
       if csSubComponent in Component.Components[I].ComponentStyle then
         Include(Component.Components[I].FComponentState, csWriting);
         
     if Assigned(FAncestorList) then
       Ancestor := FindAncestor(Component.Name);
     if Assigned(FOnFindAncestor) and ((Ancestor = nil) or
     (Ancestor is TComponent)) then
     begin
       AncestorComponent := TComponent(Ancestor);
       FOnFindAncestor(Self, Component, Component.Name, AncestorComponent,
         FRootAncestor);
       Ancestor := AncestorComponent;
     end;
     Component.WriteState(Self); //写入属性
     
     Exclude(Component.FComponentState, csWriting);//写入完后再将csWriting复位
     for I := 0 to Component.ComponentCount - 1 do
       if csSubComponent in Component.Components[I].ComponentStyle then
         Exclude(Component.Components[I].FComponentState, csWriting);
   finally
     Ancestor := OldAncestor;
     FRootAncestor := OldRootAncestor;
   end;
 end;

 

procedure TWriter.WriteRootComponent(Root: TComponent);//将Ancestor参数以nil值传入,调用WriteDescendant方法写入部件

begin
   WriteDescendent(Root, nil);
 end;

 

//先调用WriteSignature方法写入Filer对象标签。然后调用WriteComponent将部件Root写入流

procedure TWriter.WriteDescendent(Root: TComponent; AAncestor: TComponentbegin);
   FRootAncestor := AAncestor;
   FAncestor := AAncestor;
   FRoot := Root;
   FLookupRoot := Root;
   WriteSignature;
   WriteComponent(Root);
 end;

procedure TStream.WriteDescendent(Instance, Ancestor: TComponent); //创建了TWriter对象,然后利用TWriter的WriteDescendant方法将Instance写入流。

var
   Writer: TWriter;
 begin
   Writer := TWriter.Create(Self, 4096);
   try
     Writer.WriteDescendent(Instance, Ancestor);
   finally
     Writer.Free;
   end;
 end;

 

流TStream

procedure TStream.WriteDescendent(Instance, Ancestor: TComponent); //创建了TWriter对象,然后利用TWriter的WriteDescendant方法将Instance写入流。
 var
   Writer: TWriter;
 begin
   Writer := TWriter.Create(Self, 4096);
   try
     Writer.WriteDescendent(Instance, Ancestor);
   finally
     Writer.Free;
   end;
 end;procedure TStream.WriteComponent(Instance: TComponent); //WriteComponent方法只是简单地调用WriteDescendant方法将Instance写入流
 begin
   WriteDescendent(Instance, nil);
 end;