Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.02.03;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.62 MB
Время: 0.043 c
2-1199558731
Riply
2008-01-05 21:45
2008.02.03
Разница в вызове функций


2-1199727919
T54
2008-01-07 20:45
2008.02.03
TTreeView


4-1183109513
евнен
2007-06-29 13:31
2008.02.03
форматирование диска без участия пользователя


15-1198361045
linkomizin
2007-12-23 01:04
2008.02.03
нужно к 24.12.07..


11-1183049737
Nikfel
2007-06-28 20:55
2008.02.03
Как создать свой компонент.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский