Delphi: Храните данные в некоторой структуре - PullRequest
2 голосов
/ 18 августа 2011

Для программы симуляции я работаю в Delphi 2010. Симуляция не проблема, но мне нужно использовать большой набор данных, который создает проблему.Данные доступны в таблицах Excel, поэтому нет необходимости редактировать эти данные в Delphi, но сбор этих данных из таблиц Excel занимает около 10 минут.Это не проблема, если вам не нужно собирать данные при каждом запуске программы.Поэтому я сделал программу, которая собирает все данные, делает их видимыми, а не проблемы здесь, а затем сохраняет их.Однако я не могу сохранить его в «формате Delphi», не потеряв структуру, поэтому его можно загрузить за несколько секунд.

Я не настолько опытен в Delphi и долго искалрешение, но не мог понять, что было лучше.Я думаю, что мой способ структурирования данных неправильный, но он был прост и работал.Однако, если есть более эффективные способы хранения данных, пожалуйста, скажите об этом, но помните, что мне нужно больше объяснений, чем просто использовать «XML-файл», «generict» или «Ttreeview».(прочитал его, но не смог его использовать).

Данные для: я сделал этот продукт, следующий продукт, который я делаю, это, так что мне нужно очистить?True или false.

Данные хранятся в виде класса (TObject) с Productnumber (целое число) и List, который содержит все продукты, которые могут быть созданы следующим. Этот список содержит другой класс (TObject) с Productnumber (целое число) и мне нужно очистить (логическое значение).Я хочу сохранить эту структуру в файле, не теряя данные, и прочитать ее обратно в ту же структуру.

Я надеюсь, что кто-то может помочь.Заранее спасибо.

Обновление: код для предоставления чуть более подробной информации (изменен на английский)

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 ]

19 голосов
/ 18 августа 2011

Вам нужен так называемый механизм «сериализации».

1.Стандартный способ

1.1 SaveToStream

В Delphi мы обычно реализуем метод SaveToStream, который сохраняет содержимое каждого объекта в месте назначения TStream (либо TFileStream, либо TMemoryStream).

Вам нужно будет написать сериализацию вручную.

1.2 DFM-подобная потоковая передача

См. TWriter / TReader классы.

Если вы определили свои данные в опубликованных свойствах, вы можете сериализовать их, используя этистандартные классы Delphi.

Для некоторых методов, способных сериализовать любой TCollection контент JSON и от него, см. эту статью блога .

2.RTTI

См., Например, этот вопрос SO .

В частности, новый расширенный RTTI (доступен с Delphi 2010) открывает новые возможности для сериализации.

3.Используйте записи вместо классов

Если каждый элемент не хранит много содержимого (некоторое целое число / логическое значение), может иметь смысл использовать записи вместо объектов.Для скорости и потребления / фрагментации памяти это может стоить.

Вот некоторая оболочка, способная сериализовать любой динамический массив , даже содержащий вложенные записи или динамические массивы.

4.Используйте ядро ​​базы данных

Возможно, лучшим подходом является не зацикливание ваших данных в не развивающейся двоичной форме, проприетарной для вашего приложения.Если вы хотите добавить свойство, вам придется управлять им вручную.Или, если вы хотите получить доступ к вашим данным из других приложений, это может быть затруднено.

Существует множество решений для баз данных - вместо использования внешней базы данных (например, MS SQL, FireBird или Oracle), это можетХорошей идеей будет встроить базу данных в ваше приложение (намного проще в установке).Стоит упомянуть SQLite с множеством оберток , включая нашу версию (которая позволит вам перейти на любую другую базу данных, если вы хотите использовать MS SQL илиOracle вместо).

У вас есть другие решения - см. этот вопрос SO - и, если вам нужна производительность, взгляните на нашу библиотеку Big Table .

2 голосов
/ 18 августа 2011

Добавьте 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;

Это общая идея ... как загрузить данные обратно также должно быть понятно.Суть версии файла заключается в том, что при изменении объекта данных (т.е. при добавлении какого-либо свойства) вы можете увеличивать номер версии, чтобы в коде загрузки вы могли загружать данные в нужную версию объекта данных.

0 голосов
/ 18 августа 2011

Я бы выбрал вариант 4 для Arnoud, но использую ClientDataSet с вложенными ClientDataSets.Это позволит вам загружать и сохранять данные в гибкой структуре, а также быстро их отображать.Проверьте эту страницу , а также здесь для получения информации и примеров вложенного набора данных.

...