【问题标题】:Delphi: Store data in somekind of structureDelphi:以某种结构存储数据
【发布时间】:2011-10-29 16:16:22
【问题描述】:

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

我在 Delphi 方面没有那么丰富的经验,我搜索了很长时间的解决方案,但不明白什么是最好的。我认为我构建数据的方式是错误的,但它既简单又有效。但是,如果有更好的存储数据的方法,请这样说,但请记住,我需要更多的解释,而不仅仅是使用“xml 文件”、“generict”或“Ttreeview”。 (已阅读但无法使用)。

数据是:我做了这个产品,下一个我做的产品是这个,我需要清洗吗?对或错。

数据存储为带有 Productnumber(整数)的类(TObject)和一个包含接下来可以制作的所有产品的列表。此列表包含另一个带有 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;

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

【问题讨论】:

  • 有点难猜你的数据结构是什么……你说的“clean(boolean)”是什么意思:一个布尔属性?
  • @Arnand:据我所知,一个布尔值,意思是“我需要清理(清理)吗”。
  • “我认为我构建数据的方式是错误的,但它简单且有效” - 如果数据结构简单且有效,那怎么可能是错误的?

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


【解决方案1】:

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;

我假设您有一些“根对象”列表,因此您可以创建一个函数或方法,将它们保存/加载到流 ie 中/从流中加载

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;

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

【讨论】:

  • 仍然缺少一个 Create 构造函数来初始化内部 FChildProducts 实例......和一个析构函数来释放它......
  • @Arnaud 是的,代码只是为了展示这个想法,而不是完美的即用型库。编写所有代码需要花费太多精力......但它应该启动 OP。
  • 对于 OP 阅读所有这些代码已经非常好。直接在 SO 中编写代码总是一种努力。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多