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

Вниз

Сохранение array в FileStream   Найти похожие ветки 

 
Deus   (2002-02-13 13:55) [0]

Здравствуйте.

Как я могу сохранить содержимое массива в файл?
Вариант перебора всех элементов - не походит, так как аррей не простой, а состоит из рекордов, которые тоже в свою очередь имеют нетривиальную струкуру(которая вдобавок может меняться).
Хочется найти простое решение(типа FileStream.write(MyArray, sizeof(MyArray));)


 
Digitman (M) ©   (2002-02-13 14:14) [1]

>>"Хочется найти простое решение.."
Так сам будешь искать ? Или помощи все же просишь ? Если - помощи, то - где декларация массива ? Хочешь поиграть в "Угадайте с 3-х раз, какой у меня аррей" ?


 
Deus   (2002-02-13 14:22) [2]

Спокойно, спокойно.
Дело-то как раз в том, что мне хочется найти решение независимо от формата массива.

А массив такой:

type TActions=(acSendKey, acOther);
type TModKeys=(mkShift, mkControl, mkAlt);
type TOther=(oVolUp, oVolDown, oMute, oMyComp, oRunProgram);
Type TDoAction=record
ExtKey:TExtKey;
Actions:TActions;
Caption:string;
StandardKey:integer;
Modifiers:TModKeys;
Others:TOther;
RunProgram:string;
end;
Actions:Array of TDoAction;



 
Юрий Зотов (M) ©   (2002-02-13 14:34) [3]

Я бы попробовал вот что.

type
TMyRecord = packed record
... // что угодно
end;

TMyArray = packed array of TMyRecord;

var
MyArray: TMyArray;
N: LongWord;
...

// Запись:
N := Length(MyArray);
FileStream.Write(N, SizeOf(N)); // Будет нужно при чтении
FileStream.Write(MyArray[0], N * SizeOf(TMyRecord));

// Чтение:
FileStream.Read(N, SizeOf(N));
SetLength(MyArray, N * SizeOf(TMyRecord));
FileStream.Read(MyArray[0], N * SizeOf(TMyRecord));



 
Digitman (M) ©   (2002-02-13 14:38) [4]

Такого (универсального, да еще и - "простого") решения ты не найдешь. И не пытайся даже. Хотя "простое" - понятие растяжимое) Судя по твоему пониманию, "простое" решение есть решение "типа" в одну строчку кода...

Конкретное решение (будь оно "простое" или "золотое") в такой задаче зависит от конкретной структуры элемента массива. Для дан.массива следует еще определиться в декларации типа TExtKey - ты не привел ее, а ведь этот тип используется в декларации типа TDoAction ...

Чему, по-твоему, будет равно значение sizeof(MyArray) для приведенной декларации ? Из чего оно складывается ?


 
Vuk ©   (2002-02-13 14:56) [5]

Решение "в лоб". Сделать из записи CollectionItem, поля сделать published свойствами, а массив-компонентом имеющим в качестве published-свойства коллекцию. После этого всю работу по сохранению/загрузке можно свалить на стандартные механизмы сериализации.


 
Digitman (M) ©   (2002-02-13 15:21) [6]

>Vuk
А ведь ты не упоминаешь при этом, что TCollectionItem еще нужно "научить" писать/читать себя в/из поток(а), прежде чем вызывать Read/WriteCollection(). Далеко не всегда можно сложные/составные/объектные типы заставить "автоматом" читать/писать свое "нутро" в поток, будь они хоть трижды Published. Ведь так ? В таком случае, вряд ли это можно назвать "простым" решением (по автору) - реализовать в одну строчку (имеется ввиду : описать и реализовать класс все же сложнее, чем описать и объявить просто массив, будь он хоть трижды "сложный"). Это уже "пахнет" пересмотром структуры программы в целом, а оно, как кажется, автором не подразумевается в числе вариантов решения проблемы


 
Vuk ©   (2002-02-13 15:35) [7]

>А ведь ты не упоминаешь при этом, что TCollectionItem еще нужно
>"научить" писать/читать себя в/из поток(а), прежде чем вызывать
>Read/WriteCollection().
В большинстве случаев ничего этого не нужно. Правда, в данном случае единственное, чего мы не знаем - что за тип TExtKey. Если он элементарный (не составной) как и все остальное, то для все будет работать автоматом, поскольку свойства типа "коллекция" отрабатываются в TReader/TWriter автоматически (см. ReadCollection / WriteCollection) и сохраняются все published свойства элементов коллекции.

>Это уже "пахнет" пересмотром структуры программы
Я просто привел пример подхода, который сам часто использую. Что в данном случае более правильно - решать автору вопроса.


 
Deus   (2002-02-13 16:07) [8]

Сорри что забыл про TExtKey. Вот он:
TExtKey=record
VirtualKeyCode: Cardinal;
ScanCode: Byte;
isExtendedKey: Boolean;
altIsDown: Boolean;
Name:String;
end;

Решение коллекшн->компонента->Stream.WriteComponent - я в общем к этому и склонялся, но мне кажется, должен быть более простой способ.
Возможно, я в корне не прав, но я так рассуждаю:
Массив(любой) - просто некая область в памяти. Разделённая на равные куски(каждый из которых - элемента массива), или имеющая некий индекс в начале. => эту область в памяти можно записать в стрим и потом считать обратно в подготовленную область. Дельфи использует первую модель, но насколько я понял, он хранит не данные, а указатели на них... Тут затык :((


 
vuk ©   (2002-02-13 16:12) [9]

Затык не здесь а в строках. Именно они хранятся в виде указателей. А все остальное (если дело экземпляров классов не касается) будет храниться непосредственно в массиве.


 
vuk ©   (2002-02-13 16:15) [10]

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


 
Deus   (2002-02-13 16:34) [11]

Нашёл решение:
Type TDoAction=record
ExtKey:TExtKey;
Actions:TActions;
Caption:string[255];
StandardKey:integer;
Modifiers:TModKeys;
Others:TOther;
RunProgram:string[255];
end;

.....
ss:=TFileStream.Create(sd.FileName,fmOpenWrite or fmCreate);
for i:=0 to length(actions)-1 do begin
ss.Write(actions[i].ExtKey, sizeof(actions[i].ExtKey));
ss.Write(actions[i].Actions, sizeof(actions[i].Actions));
ss.Write(actions[i].Caption, sizeof(actions[i].Caption));
ss.Write(actions[i].StandardKey, sizeof(actions[i].StandardKey));
ss.Write(actions[i].Modifiers, sizeof(actions[i].Modifiers));
ss.Write(actions[i].Others, sizeof(actions[i].others));
ss.Write(actions[i].RunProgram, sizeof(actions[i].RunProgram));
end;
ss.Free;

Работает....


 
Deus   (2002-02-13 16:42) [12]

2Юрий Зотов:
Попробовал, как Вы предлагали - не работает.


 
vuk ©   (2002-02-13 16:44) [13]

Ну да, это короткие строки (shortstring) они хранятся не в виде указателя. Но я бы на Вашем месте писал строки немного иначе - чтобы лишнее место в потоке не занимать.

ss.write( actions[i].caption[0], length(actions[i].caption)+1 );

соответственно чтение можно делать примерно так:
read( actions[i].caption[0], 1 );
read( actions[i].caption[1], length(actions[i].caption));


 
Юрий Зотов (M) ©   (2002-02-13 17:16) [14]

С короткими строками должно работать. Естественно, Name в TExtKey тоже должна быть короткой. Проверьте.


 
Digitman (M) ©   (2002-02-13 17:23) [15]

>Deus
Решение-то ты rfr ,s нашел) ... но - подгонкой исх.структуры под конечный результат ... а вот если - "не подгонять" ? Неужели не таким "простым" уже кажется решение ? к примеру, от <vuk> (13.02.02 16:44) ??


 
vuk ©   (2002-02-13 17:37) [16]

to Digitman:
То что я писал относится к shortstring. Для string решение будет другим - с установкой длины строки при считывании. Приводить код, ввиду его тривиальности, не буду.


 
Deus   (2002-02-13 17:44) [17]

2Digitman: почему не простым? Vuk просто подсказал, как сделать решение более оптимальным... Подгонка никакая не потребовалась - замена String на ShortString - не в счёт. Плохо то, что приходится каждый элемент записи в каждом элементе массива сохранять отдельно - но тут я никакого выхода не вижу.

2Юрий Зотов: конечно. К тому же каждый элемент TExtKey приходится сохранять отдельно...

2All: Большое всем спасибо за оперативную помощь!



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

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

Наверх




Память: 0.51 MB
Время: 0.013 c
7-9298
Unkown
2001-11-26 12:26
2002.03.04
Чем протестировать компьютер?


1-9203
Анонимщик
2002-02-14 10:54
2002.03.04
Помогите с печатью метафайла


1-9162
foks
2002-02-02 11:19
2002.03.04
У меня не работает Delphi 5.0 из под Windows XP


7-9316
Aza
2001-11-27 06:58
2002.03.04
Hook на клаву


3-9083
IronHawk
2002-02-06 18:44
2002.03.04
Данные из QuickReport.Preview сохранять в *.dbf или *.db файл !!!