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

Вниз

Сохранение динамического массива в файл   Найти похожие ветки 

 
Mixail   (2008-01-10 15:06) [0]

Не подскажете ли, как сохранить в файл динамический массив, который является свойством объекта Record? Попытался с функцией SetLength(), но после сохранения и обратной загрузки данных из файла выводятся пустые строки.


 
Евгений Р.   (2008-01-10 15:13) [1]

f:file;
n:integer;
n:=размер заполненной части массива

BlockWrite(f,n,1);


 
Palladin ©   (2008-01-10 15:15) [2]


> Не подскажете ли, как сохранить в файл динамический массив,
> который является свойством объекта Record?

в типизированный файл - никак


 
Mixail   (2008-01-10 15:16) [3]

Спасибо за совет, Евгений Р.
Попробую ваш вариант. Я применял TFileStream, но не получалось.


 
Джо ©   (2008-01-10 15:20) [4]

Приведите объявление массива.


 
clickmaker ©   (2008-01-10 15:23) [5]

"динамический массив" и "пустые строки" - это массив из String, что-ли?


 
Palladin ©   (2008-01-10 15:26) [6]


> [1] Евгений Р.   (10.01.08 15:13)

ню ню...


> [3] Mixail   (10.01.08 15:16)

ну у тебя ошибка в 17 строке...

Type
TMyRec=Record
 a:Array of Integer;
 b:Array of Byte;
End;

Procedure SaveRec(fs:TFileStream;r:TMyRec);
Var
 n:Integer;
Begin
 n:=Length(r.a);
 fs.Write(n,SizeOf(n)*SizeOf(Integer));
 fs.Write(r.a[0],n*SizeOf(Integer));
 n:=Length(r.b);
 fs.Write(n,SizeOf(n));
 fs.Write(r.b[0],n);
End;

Procedure ReadRec(fs:TFileStream;Var r:TMyRec);
Var
 n:Integer;
Begin
 fs.Read(n,SizeOf(n));
 SetLength(r.a,n);
 fs.Read(r.a[0],n*SizeOf(Integer));
 fs.Read(n,SizeOf(n));
 SetLength(r.b,n);
 fs.Read(r.b[0],n);
End;


чего сложного то?


 
Mixail   (2008-01-10 15:28) [7]

clickmaker, ни строки, ни цифры не сохраняются. При переводе того же массива на статический, данные сохраняются.


 
Palladin ©   (2008-01-10 15:30) [8]

ошибся при записи... пусть будет заданием на дом...


 
Плохиш ©   (2008-01-10 15:32) [9]


> Mixail   (10.01.08 15:28) [7]

Сказали же уже "ошибка в 17й строке"


 
Mixail   (2008-01-10 15:41) [10]

"ошибка в 17й строке" кода своего автора, а я не указывал свой код


 
Сергей М. ©   (2008-01-10 15:41) [11]


> При переводе того же массива на статический, данные сохраняются


Это означает только одно - ты не понимаешь разницы между статическим и динамическим массивами.


 
Сергей М. ©   (2008-01-10 15:43) [12]


> Mixail   (10.01.08 15:41) [10]


> я не указывал свой код


Ну и продолжай париться.


 
Mixail   (2008-01-10 15:52) [13]

Сергей М., по-моему ты перепутал этот форум с развлекательными. Никто не нуждается в оценке "потенциала понимания". Мне действительно нужен совет по применению динамического массива внутри объекта Record, и сохранению его в файл через TFileStream.


 
Palladin ©   (2008-01-10 15:54) [14]

:) чукча не читатель, чукча писатель


 
Сергей М. ©   (2008-01-10 15:55) [15]


> Mixail   (10.01.08 15:52) [13]



> ты перепутал


Угу.
Который уже год путаю.


> применению динамического массива внутри объекта Record


Ничто не мешает этому применению.
Обычным образом оно осуществляется.


> и сохранению его в файл


см. [11]
Как только поймешь, так и вопросы сами по себе отпадут.


 
Сергей М. ©   (2008-01-10 15:56) [16]


> Mixail   (10.01.08 15:52) [13]


Тебе, чукче, уже в [6] дали тот самый вожделенный совет)


 
Юрий Зотов ©   (2008-01-10 16:17) [17]

> Mixail

Запись файла:
1. Пишем в файл целое число длиной 4 байта (кол-во эл-тов в массиве)
2. Пишем сами элементы.

Чтение файла:
1. Читаем 4 байта в целую переменную.
2. Устанавливаем длину массива.
3. Читаем элементы массива.


 
Mixail   (2008-01-10 16:24) [18]

Юрий, имеешь ввиду целое число внутри Record? И как связать это целое число с самими элементами? Прошу совета.


 
@!!ex ©   (2008-01-10 16:38) [19]

> [18] Mixail   (10.01.08 16:24)

Че за идиотизм?? Ответили уже раз десять...
Уважаемый, послушайте Сергея, он вам дело говорит, учите матчасть, и втыкайте в различия между статическим и динамическим массивом...

type
 MyRec=record
   T:array of Items;
   Count:integer;
 end;

var
 Index:integer;
begin
 Write(Count);
 for Index:=0 to Count-1 do
   Write(T[Index]);
end;


 
Palladin ©   (2008-01-10 16:41) [20]


> [19] @!!ex ©   (10.01.08 16:38)

а count то на кой? [6] смотрел?


 
Плохиш ©   (2008-01-10 16:46) [21]


> Palladin ©   (10.01.08 16:41) [20]

Так ведь "Чем дальше в лес, тем толще партизаны" :-))


 
Юрий Зотов ©   (2008-01-10 16:50) [22]

> Mixail   (10.01.08 16:24) [18]

> целое число внутри Record?

Нет. Никакие Record тут вообще ни при чем. Есть массив, который надо записать в файл. И без разницы, где этот массив находится - в Record или нет. Сначала пишем в файл длину массива (4 байта), потом сам массив.

То же самое при чтении. Есть файл, который надо прочитать в массив. И снова без разницы, где этот массив находится - в Record или нет. Сначала читаем из файла 4 байта, потом устанавливаем длину массива, потом читаем сам массив.

Есть одно "но" - если это массив длинных строк, то каждую строку надо писать (и читать) по той же схеме - сначала длину строки (4 байта), потом тело строки.

> @!!ex ©   (10.01.08 16:38) [19]

Поле Count внутри MyRec - лишнее.


 
Сергей М. ©   (2008-01-10 17:02) [23]


> Mixail   (10.01.08 16:24) [18]


Ты вообще соизволил проанализировать [6] ?
Или писатель ?)


 
@!!ex ©   (2008-01-10 17:05) [24]

> а count то на кой?


> Поле Count внутри MyRec - лишнее.

Это привычка... Часто приходится пользоваться данимаческими массивами вида: type TDynamycarray = array[0..0] of TItem;
Вот и забываю все время, что размер стандартного дин. массива можно узнать с помощью Length.


 
Mixail   (2008-01-11 16:28) [25]

Обращаюсь истинным и щедрым мастерам Дельфи: уже несколько дней мучаюсь с динамическими массивами структуры (записи).  Покопался во всей документации Borland, ничего не вышло – структура с динамическими массивами не сохраняется в файл. Вчера ребята посоветовали пару вариантов, но и это не помогло. Дело в том, что проблема не с объявлением длины массива – хоть сохрани значение длины массива в самом файле, хоть объяви константой – не работает, точнее исключений не вызывает, но данные не сохраняются в файле. Нужно в файле сохранить структуру в целом (fs.Read(Rec, sizeof(Rec))), а не каждое свойство по отдельности, так как таких свойств у моей струтуры масса. Один ньюанс – как только переводишь динамический массив на статический и убираешь функции SetLength(), структура сохраняется, словно это не тот самый код.

Прошу мастеров, подправьте, пожалуйста, код ниже – я его максимально сократил, оставил две процедуры, работающие с двумя свойствами структуры и двумя компонентами TMemo. Буду искренне благодарен за помощь. michail_col@yahoo.com

type
MyRecord = record
MyShortStr: array of shortstring;    // первое свойство
//...                                                    // второе и последующие свойства
MyWideStr: array of shortstring;     // последнее свойство
end;
...
var
 Form1: TForm1;
 Rec: MyRecord;

implementation
{$R *.dfm}

procedure TForm1.FormShow(Sender: TObject);
var
fs: TFileStream;
n: integer;
begin
SetLength(Rec.MyShortStr,3);
SetLength(Rec.MyWideStr,3);

 if FileExists("MyRec.dat") then begin
  fs:=TFileStream.Create("MyRec.dat", fmOpenRead);
  fs.Read(Rec, sizeof(Rec));
  fs.Free;

  for n:=0 to 2 do Memo1.Lines.Add(Rec.MyShortStr[n]);
  for n:=0 to 2 do Memo2.Lines.Add(Rec.MyWideStr[n]);
 end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
fs:TFileStream;
n: integer;
begin
 for n:=0 to 2 do Rec.MyShortStr[n]:= Memo1.Lines.Strings[n];
 for n:=0 to 2 do Rec.MyWideStr[n]:= Memo2.Lines.Strings[n];

 fs:=TFileStream.Create("MyRec.dat", fmCreate);
 fs.Write(Rec,sizeof(Rec));
 fs.Free;
end;
end.


 
Palladin ©   (2008-01-11 16:31) [26]


> [25] Mixail   (11.01.08 16:28)

идентификатор динамического массива является ссылкой, на кой тебе ссылки в файле? тебе уже Сергей М. сколько раз намекнул поизучать, а ты так ничего и не понял! ты даже на мой код неудосужился глянуть. сразу бы понял что к чему. И ЮЗ тебе про то же твердит, а все в лоб да полбу...


 
Mixail ©   (2008-01-11 16:35) [27]

Palladin, твой код я не только просмотрел - и применил - строки не сохраняются. Используй shortstring или widestring вместо integer внутри record, потом проверь, работает ли.


 
Palladin ©   (2008-01-11 16:37) [28]

ты не путай теплое с мягким! нижний индекс дин массива = 0 нижний индекс строки 1
соответсвенно дабы мой код заработал и со строками нужно изменить a[0] на a[1]


 
Сергей М. ©   (2008-01-11 16:37) [29]


> уже несколько дней мучаюсь


Канонизировать твой труп никто, думаю, не собирался.


 
@!!ex ©   (2008-01-11 16:39) [30]

> [25] Mixail   (11.01.08 16:28)

Yo!! АЛЕ!!! НЕльзя днимаический фалй так сохранять!!!
Вы бы еще List так сохранили... или class...
Динамический массив нужно сохранять отдельно! либо поэлементно, либо как в [6](только надо понимать, что это работает, только если работаем с массивом элементарных структур, без указателей)


 
Германн ©   (2008-01-11 16:40) [31]


> Есть одно "но" - если это массив длинных строк, то каждую
> строку надо писать (и читать) по той же схеме - сначала
> длину строки (4 байта), потом тело строки.
>

(c) Юрий Зотов ©   (10.01.08 16:50) [22]

И всё-таки ты чукча.


 
Dennis I. Komarov ©   (2008-01-11 16:41) [32]

> [25] Mixail   (11.01.08 16:28)

Ну как вот тебе помочь, если ты сам себе не хочешь...
Что хранится в Rec.MyShotStr ?


 
Dib@zol ©   (2008-01-11 16:42) [33]

Вощем так. Слухай сюды.

Что такое статический массив? Это тот, который размещается в памяти заранее, сразу при старте проги. То есть, память под него заранее отведена. Так? Так. И записывается он в файл именно потому, что твой код читает побайтно етот кусок памяти и пишет его в файл.

А что мы имеем с массивом динамическим? Память под него выделяется по запросу программы, и может быть разного размера. Именно потому резевиовать память статически - нет смысла. А вдруг её окажется мало? А вдруг наоборот не хватит? Поэтому под динамический массив отводится всего четыре байта. Почему так мало, спросишь ты? Отвечаю: в ентих 4-х байтах записывается всего лишь адрес первого байта нашего массива. который физически расположен совершенно в другом куске памяти, нежели тот где ты его ищешь.

Вывод: кури хелп по динамическим массивам до полного просветления.


 
Сергей М. ©   (2008-01-11 16:43) [34]


> просмотрел - и применил - строки не сохраняются.


Басурманин ?)


 
Mixail ©   (2008-01-11 16:44) [35]

Palladin, дело не в индексе, нижний индекс строки указал 0. Кроме того, если у меня 15 свойств в структуре, придется каждый читать и сохранить по-отдельности. Неужели невозможно поработать с длинами дин.массивов до чтения и сохранения, а в файл сохранить только саму структуру в целом.


 
Palladin ©   (2008-01-11 16:47) [36]


> нижний индекс строки указал 0

Я тебе повторяю, нижний индекс строки 1 (один), мой пример для дин массивов, они с 0 (нуля)


> Кроме того, если у меня 15 свойств в структуре, придется
> каждый читать и сохранить по-отдельности. Неужели невозможно
> поработать с длинами дин.массивов до чтения и сохранения,
> а в файл сохранить только саму структуру в целом.

да, к сожалению (а ксожалению ли?) это так. Еслиб было все так просто, то и объекты классов было бы здорово сохранять. Почему нельзя сохранить одной операцией подробно разжевал [33] Dib@zol ©   (11.01.08 16:42)


 
Palladin ©   (2008-01-11 16:48) [37]


> [35] Mixail ©   (11.01.08 16:44)

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


 
@!!ex ©   (2008-01-11 16:50) [38]

> Еслиб было все так просто, то и объекты классов было бы
> здорово сохранять.

Поэтому есть сериализация, которую, кстати, можно было бы не плохо применить к этой записи, раз уж она такая большая...

Правда я ни разу не видел, чтобы сериализацию на дельфе делали, хотя может не туда смотрел...


 
Palladin ©   (2008-01-11 16:52) [39]


> [38] @!!ex ©   (11.01.08 16:50)

вот тут сразу возникает вопрос, а нужен ли вообще Record, может Class таки сделать... заодно какой нибуть красивой функциональностью обрастить...


 
Mixail ©   (2008-01-11 16:55) [40]

Palladin, попытаюсь с "1". Если обратили внимание, я указал свойство "MyWideStr", а его тип назначил shortstring. Когда использовал  массив из widestring даже внутри статического массива, при чтении из файла прога вызывает исключение. А применив массив из single, в результате получаю искаженные значение, обычно длинные значения после DecimalSeparator. Из-за чего, по-вашему?


 
Palladin ©   (2008-01-11 16:56) [41]


> [40] Mixail ©   (11.01.08 16:55)


> Когда использовал  массив из widestring даже внутри статического
> массива, при чтении из файла прога вызывает исключение


> А применив массив из single, в результате получаю искаженные
> значение, обычно длинные значения после DecimalSeparator.


кусочек кода записи/чтения покажи, так никто тебе не скажем в чем ошибка


 
Mixail ©   (2008-01-11 17:00) [42]

Palladin, тот же самый код, со статическим массивом:

type
MyRecord = record
SingleNn: array [0..9] of single;    
WideStr: array [0..9] of widestring;    
end;

fs:=TFileStream.Create("MyRec.dat", fmCreate);
fs.Write(Rec,sizeof(Rec));
fs.Free;


 
Сергей М. ©   (2008-01-11 17:05) [43]


> Mixail ©   (11.01.08 17:00) [42]


И в чем проблема, ув. Михуил ?

По случаю уж децл вопросов:

- где packed record ?
- какого ляда ты пользуешь Write вместо WriteBuffer ?
- как объявлен Rec ?


 
Palladin ©   (2008-01-11 17:10) [44]

ну ты молодец конечно, singl"ы должны сохранится как есть, а вот с WideStr проблемка, WideStr:array [0..9] of widestring есть 10 элемеyтов указателей, вот ты эти указатели и сохраняешь, тут не прокатит так просто

надо так

var
n:Integer;

fs:=TFileStream.Create("MyRec.dat", fmCreate);
fs.Write(Rec.SingleNm,SizeOf(Rec.SingleNm));
for i:=0 to 9 Do
Begin
 n:=Length(Rec.WideStr[i]);
 fs.Write(n,SizeOf(n));
 fs.Write(Rec.WideStr[i][1],n*2); // бо размер символа в WideStr 2 байта
End;
fs.Free;

соответственно код чтения
Var
n:Integer;

fs.Read(Rec.SingleNm,SizeOf(Rec.SingleNm));
For i:=0 to 9 Do
Begin
 fs.Read(n,SizeOf(n))l;
 SetLength(Rec.WideStr[i],n);
 fs.Read(Rec.WideStr[i][1],n*2);
End;


 
Mixail ©   (2008-01-11 17:14) [45]

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


 
Сергей М. ©   (2008-01-11 17:17) [46]


> Mixail ©   (11.01.08 17:14) [45]


Михуил, изволь использовать packed.
Будет приятно)


 
Palladin ©   (2008-01-11 17:19) [47]


> [46] Сергей М. ©   (11.01.08 17:17)

а зачем? размер всех элементов 4 байта (в приведенном примере)


 
Mixail ©   (2008-01-11 17:22) [48]

Palladin, благодарю. Попробую твой код. А single действительно из файла возвращают искаженные цифры. Double работает нормально.


 
Palladin ©   (2008-01-11 17:25) [49]


> А single действительно из файла возвращают искаженные цифры.

такого просто не может быть... проверь таким образом

и до записи и после чтения выведи в Memo
For i:=0 to 9 do memo1.lines.add(Inttostr(Integer(Rec.SingleNm[i]));
если целочисленные значения не будут одинаковыми, то у тебя проблеммы или с записью или с чтением или и с тем и другим


 
Германн ©   (2008-01-11 17:26) [50]


> Palladin ©   (11.01.08 17:19) [47]
>
>

А разве по умолчанию не $A8 ?


 
Palladin ©   (2008-01-11 17:31) [51]


> [50] Германн ©   (11.01.08 17:26)

$A8, а что packed то даст?


 
Mixail ©   (2008-01-11 17:37) [52]

Испробовал все методы, наконец, по для экономичности вместо double решил исвользовать integer (умножив значение на 1000, а при чтении из файла разделив на 1000). Скорее проблема с записью single, т.к. значения я контролировал и до пересылки в структуру, и до записи в файл.


 
@!!ex ©   (2008-01-11 17:41) [53]

> [52] Mixail ©   (11.01.08 17:37)

скорее проблема в неупакованном рекорде... о котором Сергей талдычит вот уже несколько постов.


 
Palladin ©   (2008-01-11 17:46) [54]


> [53] @!!ex ©   (11.01.08 17:41)

еще раз говорю: упакованность рекорда монопенисуальна при чтении/записи


 
Германн ©   (2008-01-11 17:55) [55]


> Palladin ©   (11.01.08 17:46) [54]
>
>

А точно. Что запишет, то и прочитает.


 
Mixail ©   (2008-01-11 18:06) [56]

Выхожу, поэтому благодарю всех, кто уделил время на мою проблему и попытался помочь.


 
Sapersky   (2008-01-11 18:11) [57]

> Кроме того, если у меня 15 свойств в структуре, придется
> каждый читать и сохранить по-отдельности. Неужели невозможно
> поработать с длинами дин.массивов до чтения и сохранения,
> а в файл сохранить только саму структуру в целом.

да, к сожалению (а ксожалению ли?) это так. Еслиб было все так просто, то и объекты классов было бы здорово сохранять.


Есть на самом деле один хакерский трюк, который позволяет скидывать в файл подобные рекорды "одним изящным движением". Для классов, правда, подходит слабо, т.к. вложенные не видит.


 
Palladin ©   (2008-01-11 18:12) [58]

гы ^) и какой же позвольте узнать? :)


 
Dib@zol ©   (2008-01-11 18:15) [59]

Разыменование? =)

> гы ^)

Именно :)


 
Sapersky   (2008-01-11 18:27) [60]

It"s a kind of magic :)
Натурально, compiler magic. Т.е. работает по тому же принципу (и использует то же TypeInfo), что и magic-функции из system.pas (_InitializeArray/_FinalizeArray и т.п).
Всё никак не соберусь написать статью на эту тему, но пример, в принципе, есть, могу выложить.


 
Palladin ©   (2008-01-11 18:34) [61]

понятно, прикольно, через попу :)
статья да, будет полезна



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

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

Наверх




Память: 0.63 MB
Время: 0.023 c
2-1199770321
XerSon
2008-01-08 08:32
2008.02.03
Как в реестр записать и считать двоичные данные, к примеру (50)


4-1182940157
Углук
2007-06-27 14:29
2008.02.03
Вычитание регионов.


8-1172939370
tio
2007-03-03 19:29
2008.02.03
Насыщенность цветов в CMYK


4-1182855752
=BuckLr=
2007-06-26 15:02
2008.02.03
Забрать richtext из ricnedit


2-1199544501
Malik
2008-01-05 17:48
2008.02.03
Direct3D