将包含stringtypes成员的logging保存到文件(Delphi,Windows)

我有一个类似于以下的logging:

type TNote = record Title : string; Note : string; Index : integer; end; 

简单。 我select将variables设置为string(而不是一个字符数组)的原因是我不知道这些string将会是多久。 他们可以是1个字符长,200或2000.当然,当我尝试将logging保存到types文件(文件…)编译器抱怨我必须给一个string的大小。 有没有办法解决这个问题? 或者将这些logging保存到一个无types的文件中,并保持某种可search的方式?

请不要指出我可能的解决scheme ,如果你知道解决scheme,请张贴代码。 谢谢

Solutions Collecting From Web of "将包含stringtypes成员的logging保存到文件(Delphi,Windows)"

你不能使用类型化的文件。 用TFileStream尝试这样的事情:

 type TStreamEx = class helper for TStream public procedure writeString(const data: string); function readString: string; procedure writeInt(data: integer); function readInt: integer; end; function TStreamEx.readString: string; var len: integer; iString: UTF8String; begin self.readBuffer(len, 4); if len > 0 then begin setLength(iString, len); self.ReadBuffer(iString[1], len); result := string(iString); end; end; procedure TStreamEx.writeString(const data: string); var len: cardinal; oString: UTF8String; begin oString := UTF8String(data); len := length(oString); self.WriteBuffer(len, 4); if len > 0 then self.WriteBuffer(oString[1], len); end; function TStreamEx.readInt: integer; begin self.readBuffer(result, 4); end; procedure TStreamEx.writeInt(data: integer); begin self.WriteBuffer(data, 4); end; type TNote = record Title : string; Note : string; Index : integer; procedure Save(stream: TStream); end; procedure TNote.Save(stream: TStream); var temp: TMemoryStream; begin temp := TMemoryStream.Create; try temp.writeString(Title); temp.writeString(Note); temp.writeInt(Index); temp.seek(0, soFromBeginning); stream.writeInt(temp.size); stream.copyFrom(temp, temp.size); finally temp.Free; end; end; 

我将把Load程序留给你。 相同的基本思想,但它不应该需要一个临时流。 在每个条目前的记录大小,你可以阅读它,知道如果你正在寻找一个特定的记录#而不是阅读整个事情多远。

编辑:这是专门为使用Unicode字符串的Delphi版本编写的。 在较旧的版本,你可以简化它很多。

为什么不把它写成XML呢? 请参阅我的会议“ 使用Delphi的实用XML ”,了解如何开始使用。

另一种可能性是将记录制作成TComponent类的记录,并在DFM文件中存储/检索数据。

这个Stackoverflow条目告诉你如何做到这一点。

–jeroen

PS:抱歉,我的XML答案有点密集; 实际上我正在参加两个会议( BASTA!和DelphiLive!德国 )。

基本上你需要做的事情非常简单:创建一个示例XML文件,然后启动Delphi XML数据绑定向导 (从Delphi 6开始可用)。

这个向导将为您生成一个单元,它具有将XML映射到Delphi对象的接口和类,以及一些帮助函数,用于从文件中读取它们,创建一个新的对象等等。我的会话(参见上面的第一个链接)实际上包含了大多数这个过程的细节。

以上链接是一个演示Delphi XML数据绑定向导的使用的视频。

您可以使用两个不同的文件,一个以一种方便的方式存储字符串,另一个则通过引用字符串来存储记录。 这样,即使您不知道实际内容的大小,您仍然可以获得一个便于访问的记录文件。

(对不起,没有代码)

  TNote = record Title : string; Note : string; Index : integer; end; 

可以翻译为

  TNote = record Title : string[255]; Note : string[255]; Index : integer; end; 

并使用Stream.writebuffer(ANodeVariable,sizeof(TNode),但你说,在这种情况下,字符串得到超过255个字符如果一个字符串超过65535个字符,然后改变WORD为INTEGER

 type TNodeHeader=Record TitleLen, NoteLen: Word; end; (* this is for writing a TNode *) procedure saveNodetoStream(theNode: TNode; AStream: TStream); var header: TNodeHeader; pStr: PChar; begin ... (* writing to AStream which should be initialized before this *) Header.TitleLen := Length(theNode.Title); header.NodeLen := Length(theNode.Note); AStream.WriteBuffer(Header, sizeof(TNodeHeader); (* save strings *) PStr := PChar(theNode.Title); AStream.writeBuffer(PStr^, Header.TitleLen); PStr := PChar(theNode.Note); AStream.writebuffer(PStr^, Header.NoteLen); (* save index *) AStream.writebuffer(theNode.Index, sizeof(Integer)); end; (* this is for reading a TNode *) function readNode(AStream: TStream): TNode; var header: THeader PStr: PChar; begin AStream.ReadBuffer(Header, sizeof(TNodeHeader); SetLength(Result.Title, Header.TitleLen); PStr := PChar(Result.Title); AStream.ReadBuffer(PStr^, Header.TitleLen); SetLength(Result.Note, Header.NoteLen); PStr := PChar(Result.Note); AStream.ReadBuffer(PStr^, Header.NoteLen); AStream.ReadBuffer(REsult.Index, sizeof(Integer)(* 4 bytes *); end; 

您可以使用此开放源代码单元中可用的功能。

它允许您将任何记录内容序列化为二进制,甚至包括以下内容中的动态数组:

 type TNote = record Title : string; Note : string; Index : integer; end; var aSave: TRawByteString; aNote, aNew: TNote; begin // create some content aNote.Title := 'Title'; aNote.Note := 'Note'; aNote.Index := 10; // serialize the content aSave := RecordSave(aNote,TypeInfo(TNote)); // unserialize the content RecordLoad(aNew,pointer(aSave),TypeInfo(TNote)); // check the content assert(aNew.Title = 'Title'); assert(aNew.Note = 'Note'); assert(aNew.Index = 10); end;