Форум: "Основная";
Текущий архив: 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.004 c