Форум: "Начинающим";
Текущий архив: 2012.01.08;
Скачать: [xml.tar.bz2];
ВнизКак работать с двухмерным динамический массивом? Найти похожие ветки
← →
Очень Злой (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;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.003 c