Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2012.01.08;
Скачать: CL | DM;

Вниз

Как работать с двухмерным динамический массивом?   Найти похожие ветки 

 
Очень Злой   (2011-09-29 18:11) [0]

Допустим, имеется такое:
type Trec=packed record
      Id:Cardinal;
      Cnt:packed array of cardinal;
      end;
...

var
  M:packed array of Trec;
...

Вот что-то запутался...
Если я буду менять размер массива M, то массивы M[n].Cnt будут сами создаваться и уничтожаться, или нужно это самому делать c помощью New и Dispose?


 
_Юрий   (2011-09-29 18:17) [1]

создание и уничтожение динамических массивов всегда происходит автоматически, самому ничего делать не надо.
Это кстати никакой не двумерный динамический массив


 
Очень Злой   (2011-09-29 18:31) [2]


> Это кстати никакой не двумерный динамический массив


Ну видимо я не силен в терминологии...

Есть еще вопрос: Эту массив нужно "запихнуть" в поток (чтобы сохранить в файл), ну и соответственно потом прочитать из файла...

Если я сделаю:
...
       lenArray:=length(M);
       WriteBuffer(lenarray,sizeof(lenarray));
       WriteBuffer(M[0],lenarray*sizeof(M[0]));
       // далее аналогично запинем все подмассивы
...

то потом читать так:
...
       ReadBuffer(lenarray,sizeof(lenarray));
       SetLength(M,lenarray);
       ReadBuffer(M[0],lenarray*sizeof(M[0]));
       // далее аналогично загружаем все подмассивы
...
будет нельзя?
Ведь по идее я запихну вместе с полезной информацией кучу ненужных указателей, которые при чтении будут неактуальны.
правильно?


 
Servy ©   (2011-09-29 18:58) [3]

Правильно, не надо так писать, ничего хорошего из этого не выйдет, ибо динамический массив в Делфи - суть указатель, и записывать этот указатель в файл бессмысленно. Нужна дополнительная логика для сохранения всех элементов массива.

Можно сделать для вашего TRec процедуру (в новых версиях Делфи можно добавить записи метод) для сериализации одной такой записи в поток. Ну и соответствующую процедуру для десериализации записи из потока. Внутри процедуры сериализации вполне можно записывать Cnt приведенным вами способом:

procedure SaveRecToStream(const Rec: TRec; DestStream: TStream);
var
 L: Integer;
begin
 with DestStream do
 begin
   WriteBuffer(Rec.Id, SizeOf(Rec.Id));
   L := Length(Rec.Cnt);
   WriteBuffer(L, SizeOf(L));
   WriteBuffer(Rec.Cnt[0], L * SizeOf(Rec.Cnt[0]));
 end;
end;

После чего, сохранение массива таких TRec"ов можно организовать, сохранив длину массива и по очереди все записи вышенаписанной процедурой. Загрузка тоже будет выглядеть весьма очевидной - читаем длину, устанавливаем размер массива записей, читаем все записи по очереди.


 
Очень Злой   (2011-09-29 19:31) [4]

Спасибо...
Переписал для моего конкретного случая, но на всякий случай спрошу:


uses ... zlib;
...
type TPassLine = packed array[1..8] of char;

type
 TUserData = packed record
   Uin:Cardinal;
   Nick:string[16];
   password:TPassLine;
   last_auth_time:TDateTime;
   FullName:string[50];
 end;

type
 TUser=packed record
    UserData:TUserData;
    Contacts: packed array of Cardinal;
 end;

type TUserList=packed array of TUser;

...

var
 UserList:TUserList;

...

procedure UsersDataSave(filename:string);
var
 fstream:TFileStream;
 LenArray:integer;
 LenSubArray:integer;
 i:integer;
begin
 fStream:=TFileStream.Create(filename,fmCreate);
 try
   with TCompressionStream.Create(clMax,fstream) do
     try
       lenArray:=length(UserList);
       WriteBuffer(lenarray,sizeof(lenarray));
       for i:=0 to lenarray-1 do
          begin
            WriteBuffer(UserList[i].UserData,sizeof(TUserdata));
            LenSubArray:=Length(UserList[i].Contacts);
            WriteBuffer(LenSubArray,sizeof(LenSubArray));
            WriteBuffer(UserList[i].Contacts[0],length(UserList[i].Contacts));
          end;
     finally
       Free;
     end;
 finally
   fstream.free;
 end;
end;


Сохранение так правильно?


 
Dennis I. Komarov ©   (2011-09-29 19:36) [5]

XML прям сам напрашивается...


 
Servy ©   (2011-09-29 19:41) [6]


> XML прям сам напрашивается...



> with TCompressionStream.Create(clMax,fstream) do


Человек тут за байты борется, а вы про текстовый Xml :).


> [4]



> WriteBuffer(UserList[i].Contacts[0],length(UserList[i].Contacts));

SizeoOf забыт. Я бы выделил таки в отдельную процедуру сериализацию элемента, иначе читается тяжеловато, и громоздкие конструкции типа UserList[i].Contacts[0] не очень вдохновляют. Но это уже эстетика.


 
Dennis I. Komarov ©   (2011-09-29 19:48) [7]


> Человек тут за байты борется, а вы про текстовый Xml :).

Я бы понял, если бы был трафик по сетке, но ведь файл


 
Очень злой   (2011-09-29 20:59) [8]


> Dennis I. Komarov ©   (29.09.11 19:36) [5]
>
> XML прям сам напрашивается...


Были мысли насчет XML, но не в плане сохранения в нем массива, а в плане вообще отказа от массивов и непосредственной работой с XML используя TXmlDoc, но потом решил, что это может внести лишние тормоза.
А если уж работать с массивами, то в сохранении массива в XML не вижу никакой выгоды, разве что на этапе отладки.
Кроме того,


> Человек тут за байты борется, а вы про текстовый Xml :).
>
>


Не то, чтобы борюсь, но не очень люблю, когда огромные файлы состоят большей частью из "воды"...


>  SizeoOf забыт.


Хм. действительно.


> Я бы выделил таки в отдельную процедуру сериализацию
> элемента, иначе читается тяжеловато, и громоздкие конструкции
> типа UserList[i].Contacts[0] не очень вдохновляют. Но это
>
> уже эстетика.


да вроде как процедура довольно небольшая по кол-ву строк, не думаю, что ее следует разбивать на несколько...


 
Ega23 ©   (2011-09-29 21:20) [9]


unit uMain;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type

 TMyRecord = record
   ID: Cardinal;
   Cnt: array of Cardinal;
   procedure LoadFromStream(Stream: TStream);
   procedure SaveToStream(Stream: TStream);
 end;

 TForm10 = class(TForm)
   Button1: TButton;
   Memo1: TMemo;
   Button2: TButton;
   Edit1: TEdit;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form10: TForm10;

implementation

{$R *.dfm}

procedure TForm10.Button1Click(Sender: TObject);
var
 arr: array of TMyRecord;
 ms: TMemoryStream;
 i, j, arrLen: Integer;
begin
 arrLen := 5;
 SetLength(arr, arrLen);
 for i := 0 to arrLen - 1 do
 begin
   arr[i].ID := i + 1;
   SetLength(arr[i].Cnt, 5);
   for j := 0 to 4 do
     arr[i].Cnt[j] := j*100 + i;
 end;

 ms := TMemoryStream.Create;
 try
   ms.WriteBuffer(arrLen, SizeOf(Integer));
   for i := 0 to arrLen - 1 do
     arr[i].SaveToStream(ms);
   ms.SaveToFile(Edit1.Text);
 finally
   ms.Free;
 end;
end;

procedure TForm10.Button2Click(Sender: TObject);
var
 ms: TMemoryStream;
 i, j, arrLen, aCntLen: Integer;
 s: string;
 arr: array of TMyRecord;
begin
 ms := TMemoryStream.Create;
 try
   ms.LoadFromFile(Edit1.Text);
   ms.ReadBuffer(arrLen, SizeOf(Integer));
   SetLength(arr, arrLen);
   for i := 0 to arrLen - 1 do
     arr[i].LoadFromStream(ms);
 finally
   ms.Free;
 end;

 Memo1.Clear;

 for i := 0 to arrLen - 1 do
 begin
   aCntLen := Length(arr[i].Cnt);
   s := Format("ID = %d"#9"Cnt Count = %d"#9, [arr[i].ID, aCntLen]);
   if aCntLen > 0 then
   begin
     s := s + Format("Data: %d", [arr[i].Cnt[0]]);
     for j := 1 to aCntLen - 1 do
       s := s + Format(", %d", [arr[i].Cnt[j]]);
   end;
   Memo1.Lines.Add(s);

 end;

end;

{ TMyRecord }

procedure TMyRecord.LoadFromStream(Stream: TStream);
var
 i: Integer;
begin
 Stream.ReadBuffer(ID, SizeOf(Cardinal));
 Stream.ReadBuffer(i, SizeOf(Integer));
 SetLength(Cnt, i);
 Stream.ReadBuffer(Cnt[0], i * SizeOf(Cardinal));
end;

procedure TMyRecord.SaveToStream(Stream: TStream);
var
 i: Integer;
begin
 Stream.WriteBuffer(ID, SizeOf(Cardinal));
 i := Length(Cnt);
 Stream.WriteBuffer(i, SizeOf(Integer));
 Stream.WriteBuffer(Cnt[0], i * SizeOf(Cardinal));
end;

end.


 
Servy ©   (2011-09-29 21:35) [10]


> [9]

У топикстартера D7, методы к записям неподобавлять, что упоминалось в [3].

Кроме того, использование TMemoryStream вместо TFileStream для записи в файл вызывает некоторое недоумение. Чисто гипотетически, если у автора массив размером в гигабайт-полтора, то выделить еще столько же под MemoryStream для его сериализации может и не выйти. Понятно, что ситуация прямо скажем нечастая, но так как никакого профита от использования TMemoryStream не видно, то...


 
Servy ©   (2011-09-29 21:48) [11]


> А если уж работать с массивами, то в сохранении массива
> в XML не вижу никакой выгоды, разве что на этапе отладки.
>


На самом деле, этап отладки как правило самый длинный, дорогой и практически никогда не заканчивающийся - все время какой-нибудь косяк кто-нибудь где-нибудь да отроет. То есть, выгода то она есть определенная, когда на файлик, присланный пользователем, можно в блокноте глянуть и сразу понять, что к чему. Кроме того, поддержка вашего формата из других языков программирования при использовании xml куда проще - там тоже парсеры есть готовые и нет необходимости портировать эти, хоть и изящные, делфевые велосипеды.

Впрочем, xml не панацея, ибо во-первых производительность. Был бы нормальный способ бинарные данные в него пихать... А так, base64 какой-нибудь использовать приходится, что довольно печально. Во-вторых, возникающая дополнительная сложность, вместо задачи по сохранению массива вы получаете другую задачу - разбираться с xml парсерами, особенностями этого языка (типа всяких CDATA), заголовками, xslt и подобной ерундой, напрямую с решаемой задачей никак не связанной.

В общем, стоит взвесить все за и против.


 
Ega23 ©   (2011-09-29 22:37) [12]


>
> У топикстартера D7, методы к записям неподобавлять


Разве в семёрке нельзя?


> Кроме того, использование TMemoryStream вместо TFileStream
> для записи в файл вызывает некоторое недоумение.



procedure TCustomMemoryStream.SaveToFile(const FileName: string);
var
 Stream: TStream;
begin
 Stream := TFileStream.Create(FileName, fmCreate);
 try
   SaveToStream(Stream);
 finally
   Stream.Free;
 end;
end;


А поелику "ситуация прямо скажем нечастая", то профит есть и немалый, бо не надо на каждый WriteBuffer дёргать файловую операцию.


 
Ega23 ©   (2011-09-30 09:09) [13]

Не удержался вчера. Скачал и попытался установить D7 на Win7. Встало, но как-то криво. Хелп отказался запускаться, проект новый не создаётся, но новый юнит - можно. В юните по Ctrl+Shift+C на рекорде с методами ничего не произошло. Так что может быть действительно там методы в рекордах запрещены.
Но в таком случае сам Б-г велел сделать данные классом + класс-список.

TMyRecord = class (TObject)
public
 ID: Cardinal;
 Cnt: array of Cardinal;
 procedure LoadFromStream(Stream: TStream);
 procedure SaveToStream(Stream: TStream);
end;

TMyRecordList = class (TObjectList)
public
 property Items[Index: Integer]: TMyRecord read GetItem; default;
 procedure LoadFromStream(Stream: TStream);
 procedure SaveToStream(Stream: TStream);
end;


 
Очень Злой   (2011-09-30 09:58) [14]


> Но в таком случае сам Б-г велел сделать данные классом +
> класс-список.


Тоже неплохая мысль. Подумаю над этим...


 
Servy ©   (2011-09-30 22:55) [15]


> Но в таком случае сам Б-г велел сделать данные классом +
> класс-список.


Дык, с классами тогда можно от TPersistent унаследоваться, и published свойства автоматом сериализовать.


> Скачал и попытался установить D7 на Win7. Встало, но как-
> то криво.

У меня нормально работает под 64битной семеркой, если запускать с правами администратора. Хелп действительно не кажет, формат хелпа старый; можно конечно поставить какой-то костыль от майкрософта для его отображения, но мне проще пользоваться хелпом от более свежих версий.



Страницы: 1 вся ветка

Текущий архив: 2012.01.08;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.012 c
1-1279348911
set
2010-07-17 10:41
2012.01.08
Сообщение виндовс ХР


1-1279098114
packpaul
2010-07-14 13:01
2012.01.08
Реализация null-методов класса в Delphi


15-1316550580
Юрий
2011-09-21 00:29
2012.01.08
С днем рождения ! 21 сентября 2011 среда


15-1316204983
Юрий
2011-09-17 00:29
2012.01.08
С днем рождения ! 17 сентября 2011 суббота


15-1316925282
РВА
2011-09-25 08:34
2012.01.08
Подскажите по железу