Delphi:将数据存储在某种结构中

时间:2011-08-18 10:31:36

标签: delphi save delphi-2010 structure data-persistence

对于我正在Delphi 2010中工作的模拟程序。模拟不是问题,但我需要使用大量数据来解决问题。数据在Excel工作表中可用,因此无需在Delphi中编辑此数据,但从Excel工作表中收集此数据大约需要10分钟。只要您不需要在每次程序运行时收集数据,这都不是问题。所以我制作了一个程序,收集所有数据使其可见,而不是问题,然后存储它。但是我无法将其存储为“Delphi格式”,而不会丢失结构,因此可以在几秒钟内加载。

我不是那么熟悉德尔福,我搜索了很长时间才得到解决方案,却无法理解什么是最好的。我认为我构建数据的方式是错误的,但它很简单而且有效。但是,如果有更好的存储数据的方法,请说明,但请记住,我需要更多的解释,而不仅仅是使用'xml文件','generict或'Ttreeview'。 (已阅读但无法使用它)。

数据适用于:我制作了这个产品,我制作的下一个产品就是这个,所以我需要清洁吗?是对还是错。

数据存储为带有Productnumber(整数)的类(TObject)和包含下一步可以生成的所有产品的List。此列表包含另一个带有Productnumber(整数)的类(TObject)以及我需要的清理(​​布尔)。我希望将此结构保存在文件中,而不会丢失数据并将其读回相同的结构。

我希望有人可以提供帮助。提前谢谢。

更新:提供更多信息的代码(修改为英文)

Clean_from = class(TObject)
public
  myfromNumber      : Integer;
  mylist            : TList;
published
  constructor Create;
End

Clean_To = class(TObject)
public
  myToNumber        : Integer;
  Clean             : Boolean;
End;

constructor Clean_from.Create;
begin
  inherited Create;
  myList := Tlist.Create;
end;

For i = 0 to 100 do
begin
  From:= Clean_from.create;
  for j := 0 to 10 do 
  begin 
    To := Clean_To.create;
    To.clean := true or false;
    From.myList.add(To);
  end;
  GlobalList.add(from);
end;

现在我想保存包含所有内容的全局列表,以便我可以使用相同的结构加载它。

3 个答案:

答案 0 :(得分:19)

您需要的是所谓的“序列化”机制。

<强> 1。标准方式

1.1 SaveToStream

在Delphi中,我们通常会实现SaveToStream方法,该方法会将每个对象的内容保存在目标TStreamTFileStreamTMemoryStream)中。

您必须手动编写序列化。

1.2类似DFM的流媒体

请参阅TWriter / TReader课程。

如果在已发布的属性中定义数据,则可以使用这些标准Delphi类对它们进行序列化。

对于某些能够将任何TCollection序列化到 JSON 内容的方法,请参阅this blog article

<强> 2。 RTTI

例如参见this SO question

特别是,新增强的RTTI(自Delphi 2010以来可用)为序列化开辟了新的机会。

第3。使用记录而不是类

如果每个项目都不存储大量内容(某些整数/布尔值),则使用记录而不是对象可能是有意义的。对于速度和内存消耗/碎片,它可能是值得的。

这是some wrapper able to serialize any dynamic array,甚至包含嵌套记录或动态数组。

<强> 4。使用数据库引擎

也许更好的方法是不要让您的数据卡在一个非进化的二进制形式中,这是您应用程序专有的。如果要添加属性,则必须手动管理。或者,如果您想从其他应用程序访问您的数据,可能会很困难。

有很多数据库解决方案 - 而不是使用外部数据库(如MS SQL,FireBird或Oracle),将数据库嵌入应用程序(更容易安装)可能是个好主意。值得一提的SQLite a lot of wrappers,包括our version(如果你想使用MS SQL或Oracle,它将允许你更改为任何其他数据库)。

您还有其他解决方案 - 请参阅this SO question - 如果您需要表现,请查看我们的Big Table library

答案 1 :(得分:2)

SaveToStream()LoadFromStream()方法添加到数据对象中,然后将数据保存到流中并从流中加载数据。

type
  TMyData = class(TObject)
  private
    FChildProducts: TList;
    FProductnumber : integer;
    FClean: boolean;
  public
    procedure LoadFromStream(const aStream: TStream);
    procedure SaveToStream(const aStream: TStream);
  published
    property Productnumber: Integer read FProductnumber write FProductnumber;
    property Clean: Boolean reas FClean write FClean;
  end;

procedure TMyData.LoadFromStream(const aStream: TStream);
var x, cnt: Integer;
    cD: TMyData;
begin
  aStream.Read(FProductnumber, SizeOf(FProductnumber));
  aStream.Read(FClean, SizeOf(FClean));
  // read number of child products
  aStream.Read(cnt, SizeOf(cnt));
  // load child objects
  for x := 1 to cnt do begin
     cD := TMyData.create;
     cD.LoadFromStream(aStream);
     FChildProducts.Add(cD);
  end; 
end;

procedure TMyData.SaveToStream(const aStream: TStream);
var x: Integer;
begin
  aStream.Write(FProductnumber, SizeOf(FProductnumber));
  aStream.Write(FClean, SizeOf(FClean));
  // save number of child products
  x := FChildProducts.Count;
  aStream.Write(x, SizeOf(x));
  // save child objects
  for x := 0 to FChildProducts.Count - 1 do
     (FChildProducts[x] as TMyData).SaveToStream(aStream);
end;

我假设您有一些“根对象”列表,因此您可以创建一个将数据保存/加载到流中的功能或方法,即

function SaveDataList(const List: TList;const aFileName: string);
var x: Integer;
    FS: TFileStream;
begin
  FS := TFileStream.Create(aFileName, ...);
  try
     // save file version
     x := 1;
     FS.Write(x, SizeOf(x));
     // save number of products
     x := List.Count;
     FS.Write(x, SizeOf(x));
     // save objects
     for x := 0 to List.Count - 1 do
       (List[x] as TMyData).SaveToStream(FS);
  finally
     FS.Free;
  end;
end;

这是一般的想法......如何加载数据也应该清楚。文件版本就在那里,这样当数据对象发生变化时(即你添加了一些属性),你可以增加版本号,这样在加载代码中就可以将数据加载到数据对象的正确版本中。

答案 2 :(得分:0)

我会选择Arnoud的选项#4,但使用带有嵌套ClientDataSets的ClientDataSet。这将允许您在灵活的结构中加载和保存数据,并快速显示它。检查this pagehere以获取一些嵌套数据集信息和示例。