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

Вниз

Сохранение 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.005 c
1-9159
Priz_Datiy
2002-02-13 17:06
2002.03.04
Загрузка информации из файла


4-9325
Алекс
2002-01-04 09:38
2002.03.04
Помогите с SetWindowLong


3-9077
dimich
2002-02-06 11:34
2002.03.04
InterBase Server


1-9167
DJ X
2002-02-11 16:30
2002.03.04
СУПЕР СРОЧНО!!!


1-9181
Johnmen
2002-02-14 12:20
2002.03.04
Кто плотно общался с DBGridEh ?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский