将包含字符串类型的成员的记录保存到文件(Delphi,Windows) [英] saving a records containing a member of type string to a file (Delphi, Windows)

查看:152
本文介绍了将包含字符串类型的成员的记录保存到文件(Delphi,Windows)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类似于以下记录的记录:

I have a record that looks similar to:

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

简单。我选择将变量设置为字符串(而不是一个字符数组)的原因是我不知道这些字符串将要多长时间。它们可以是1个字符长,200或2000.
当然,当我尝试将记录保存到一个类型文件(...的文件)时,编译器抱怨说,我必须给一个字符串大小。
有没有办法克服这个?或者一种将这些记录保存到无类型文件的方法,并仍然保持一种可搜索的方式?

Simple. The reason I chose to set the variables as string (as opposed to an array of chars) is that I have no idea how long those strings are going to be. They can be 1 char long, 200 or 2000. Of course when I try to save the record to a type file (file of...) the compiler complains that I have to give a size to string. Is there a way to overcome this? or a way to save those records to an untyped file and still maintain a sort of searchable way?

请不要指出我可能的解决方案如果你知道解决方案,请发邮件。
谢谢

Please do not point me to possible solutions, if you know the solution please post code. Thank you

推荐答案

您不能使用类型化文件。尝试这样的一个TFileStream:

You can't do it with a typed file. Try something like this, with a 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过程给你。相同的基本思想,但它不应该需要一个临时流。在每个条目前面的记录大小,你可以阅读它,知道如果你正在寻找一个特定的记录,而不是阅读整个事情,可以跳过多远。

I'll leave the Load procedure to you. Same basic idea, but it shouldn't need a temp stream. With the record size in front of each entry, you can read it and know how far to skip if you're looking for a certain record # instead of reading the whole thing.

编辑:这是专门针对使用Unicode字符串的Delphi版本编写的。在旧版本上,您可以简化它。

This was written specifically for versions of Delphi that use Unicode strings. On older versions, you could simplify it quite a bit.

这篇关于将包含字符串类型的成员的记录保存到文件(Delphi,Windows)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆