Delphi:以某种结构存储数据

发布于 2024-11-30 11:30:34 字数 1221 浏览 0 评论 0原文

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

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

数据是:我制作了这个产品,我制作的下一个产品是这个,所以我需要清洁吗?是真是假。

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

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

For a simulation program I'm working in Delphi 2010. The simulation isn't a problem but I need to use large collection of data which gives a problem. The data is available in excel sheets, so there is no need to edit this data in Delphi, but collecting this data from the excel sheets takes around 10min. This isn't a problem as long as you don't need to collect the data every time the program runs. So I made a program which collects all the data makes it visible, not problems here,and then store it. However I can't store it to a "Delphi format" , without losing the structure, so it can be loaded in a few seconds.

I'm not that experienced in Delphi and I searched a long time for the solution but couldn't understand what was best. I think my way of structuring the data is wrong but it was simple and worked. However if there are better ways of storing the data please say so, but remember that I need some more explanation than just use 'a xml file', 'generict, or 'Ttreeview'. (have read it but wasn't able to use it).

The data is for: I made this product, The next product I make is this, so do I need to clean? True or false.

The data is stores as a class(TObject) with Productnumber (integer) and a List which contains all products that could be made next.This list contains another class(TObject) with an Productnumber (integer) and a do I need to clean(boolean). I want to save this structure in a file, without losing the data and read it back to the same structure.

I hope someone could help. Thank you in advance.

Update: The code to provide a little more information (modified to English)

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;

And now I want to save the global list with all the content so I could load it with the same structure.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

为你鎻心 2024-12-07 11:30:34

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

1.标准方式

1.1 SaveToStream

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

您必须手动编写序列化。

1.2 类似 DFM 的流式传输

请参阅 TWriter / TReader 类。

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

有关能够序列化任何 TCollection 到 JSON 内容的方法,请参阅 这篇博客文章

2. RTTI

例如参见这个SO问题

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

3.使用记录而不是类

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

这是 一些包装器能够序列化任何动态数组,甚至包含嵌套记录或动态数组。

4.使用数据库引擎

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

有很多数据库解决方案 - 与其使用外部数据库(如 MS SQL、FireBird 或 Oracle),不如将数据库嵌入到应用程序中(更容易安装)。值得一提的是SQLite,它有很多包装器,包括 我们的版本(这将允许您如果您想使用 MS SQL 或 Oracle,请更改为任何其他数据库)。

您还有其他解决方案 - 请参阅此所以问题 - 如果您需要性能,请查看我们的 大表库

What you need is the so-called "serialization" mechanism.

1. The standard way

1.1 SaveToStream

In Delphi, we usually implement a SaveToStream method, which will save the content of each object in a destination TStream (either a TFileStream or a TMemoryStream).

You'll have to write the serialization by hand.

1.2 DFM-like streaming

See TWriter / TReader classes.

If you define your data in published properties, you are able to serialize them using those standard Delphi classes.

For some methods able to serialize any TCollection to and from JSON content, see this blog article.

2. The RTTI

See for instance this SO question.

In particular, the new enhanced RTTI (available since Delphi 2010) opens new opportunities to serialization.

3. Use records instead of classes

If each item does not store a lot of content (some integer/boolean), it may make sense to use records instead of objects. For speed and memory consumption/fragmentation, it may be worth it.

Here is some wrapper able to serialize any dynamic array, even containing nested records or dynamic arrays.

4. Use a database engine

Perhaps the better approach is not to have your data stuck in a non-evolving binary form, proprietary to your application. If you want to add a property, you'll have to manage it by hand. Or if you want to access your data from other applications, it may be difficult.

There are a lot of database solutions around - instead of using an external database (like MS SQL, FireBird or Oracle), it could be a good idea to embed the database inside your application (much easier to install). Worth mentioning SQLite which has a lot of wrappers, including our version (which will allow you to change to any other database if you want to use MS SQL or Oracle instead).

You have other solutions around - see this SO question - and if you need performance, take a look at our Big Table library.

傾旎 2024-12-07 11:30:34

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;

这是一般思想...如何加载数据也应该很清楚。文件版本的存在,以便当数据对象更改(即添加一些属性)时,您可以增加版本号,以便在加载代码中您可以将数据加载到数据对象的正确版本中。

Add SaveToStream() and LoadFromStream() methods to your data object which, well, save the data to a stream and load data from a stream.

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;

I assume you have some list of "root objects" so you can make an function or method which saves/loads them to/from stream 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;

This is the general idea... how to load data back should be clear too. The file version thing is there so that when the data object changes (ie you add some property) you can increment the version number so that in the loading code you can load data into right version of the data object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文