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

Вниз

Не, ну вообще прикл...   Найти похожие ветки 

 
VitHouse   (2001-12-27 10:25) [0]

Увожаемые Мастера!

Как сохранять данные в файл, при том они могут быть разного типа
Например

TMonitor = record
Name: string;
ModelNo: integer;
end;

TComputer = record
ProcName: string;
ProcMHZ: integer;
end;


Допустим у нас два массива из мониторов и компьютеров. Как всё это сохранить в ОДИН файл, а потоп читать из него?


 
gek   (2001-12-27 10:30) [1]

Записи одинаковые зачем две делать сделай одну
TComputerMonitor = record
ProcName: string;
ProcMHZ: integer;
Name: string;
ModelNo: integer;
end;


 
VitHouse   (2001-12-27 10:42) [2]

Спасибо за интерес!
Рад познакомиться))

дело в том что мониторов и компьютеров может быть разное число, да и ещё в структуре + поле индексной связи(hComputer: THandle), т.е. мониторы отдельно, компы отдельно.
Бытовая ситуация: Монитор сгорел, купили новый, подцепили к какому то компу и т.д.
!!???


 
Delirium   (2001-12-27 10:48) [3]

Тогда это уже вопрос по БД, советую немного почитать по этому поводу и обращаться в раздел Вопросы по базам данных


 
VitHouse   (2001-12-27 10:54) [4]

THX!
да нет это просто пример, есть прога "расчет ЧЕГО-то", в которой просто ведется проект, и там куча разных типов, но это не должно работать как БД. Файл записывается, другой юзверь в нем чё-то творит и так далее... как в Ворде, или Ёкселе)


 
gek   (2001-12-27 11:03) [5]

Блин ну сделай выборку из записи

TComputerMonitor = record
ProcName: string;
ProcMHZ: integer;
Name: string;
ModelNo: integer;
end;

if ProcMHZ = 0 then//енто комп
else// енто монитор


Какие проблемы? Ну и пиши радостью в один файл-будешь счастлив


 
VitHouse   (2001-12-27 12:00) [6]

>gek
у меня 14 разных типов, и чё делать?

TComputerMonitorUserMousePrintersFloorPaperXerox?


 
gek   (2001-12-27 12:07) [7]

Или именно так (у меня как-то на турбо 7.0 около 20 полей в записи было и все енто дело в файл писал),
или делай как тебе Delirium сказал с БД работать.
Ну и последнее - упакуй запись packedи используй в записи case если уж так хочется работать таким образом


 
VitHouse   (2001-12-27 12:11) [8]

а что разве разные типы нельзя одновременно хранить?
зачем усложняться-то. Выглядит не рационально!


 
Алексей Петров   (2001-12-27 12:14) [9]

Ну введи в каждой записи первым полем байт с её размером или типом - при чтении по нему будешь разбираться, что-же такое прочиталось, и сколько байт нужно до следующей записи читать. Только от типизированного файла тогда отказаться придется - он работает строго с одним типом.


 
gek   (2001-12-27 12:27) [10]

Да ничего там сложного не будет
выборку сделай по ключу типа
case key of
1:комп
2:монитор
..
10:мышь
end;


 
VitHouse   (2001-12-27 12:40) [11]

Мне пришло предложение:

****Тело файла******
Минитор(Samsung, 17, 2, P);
Минитор(Philips, 14, 4, D);
Минитор(Akai, 15, 2, P);
Комп(700, 133, Интел, Целерон);
Комп(345, 133, Интел, Пень);
Принтер(Эпсон, 234, А4);
...
...
********************

А потом написать конверторы скриптов на каждую строку.
А все однородные типу будут храниться указателями в своем TList"e.

type ScriptFile = class
...
TComps,
TMonitors,
TPrinters: TList;
...


И в проге работать с записями из ТЛистов.
И с помощью конвертера записывать и читать файл!

Что вы думаете, господа, по этому поводу?


 
gek   (2001-12-27 12:47) [12]

Интересно как ты этот конвертор себе представляешь?


 
VitHouse   (2001-12-27 12:54) [13]

Этот конвертор распознает функции типа:
Монитор("Самсунг","20","АА");
Конвертор заполняет тип TStringFunction, Где в него прописывается имя скриптофункции и массив всех параметров!!!!!
Исходник ниже))



unit FuncConvertor10;
{Распознование функций и процедер
Версия 1.01
VitHouse ® 2001}

interface

type
TStringParams = array of string;
{Структура функции Name - Заголовок/Имя,}

PStringFunction = ^TStringFunction;
TStringFunction = record
Name: string;
Params: array of string;
end;

{Локальные явные функции}
function GetFunction (_Value: string): TStringFunction;
function FuncToStringLine (Func: TStringFunction): string;
function CreateFunction (FuncName: string; Params: array of string): TStringFunction;

{Указательные функции}
{
function GetPFunctionAddr(Value: PChar): Pointer;
function PFuncToPChar(FuncAddr: Pointer): PChar;
function CreateFunctionAddr(FuncName: PChar; Params: array of PCHar): Pointer;
}

implementation {Рутинные функции}

function CreateFunction(FuncName: string; Params: array of string): TStringFunction;
var i: integer;
l: integer;
begin
Result.Name := FuncName;
l := Length(Params);
SetLength(Result.Params, l);
for i := 0 to Length(Params) - 1 do
Result.Params[i] := Params[i];
end;


function GetCharCount(CharFind: char; _Value: string): integer;
var CharCount: integer;
Value: string;
begin
Result := 0;
Value := _Value;
CharCount{Количесво запятых} := 0;
while Pos(CharFind, Value)>0 do begin
delete(Value, Pos(",", Value), 1);
Inc(CharCount);
end;

Result := CharCount;
end;

function GetFunction(_Value: string): TStringFunction;
var Value: string;
ZapCount: Integer;
i: integer;
_Params: array of string;
begin
{
Имя функции до первой скобки (
Параметр начинается с ковычки "
Параметр заканчивается ковычкой "
Следующий параметр через запятую ,
Заканчивается функция скобкой )
}

{Этапы расспознования функции}
Value := _Value;
Result.Name := Copy(Value, 1, Pos("(", Value)-1); //Имя функции

if (Pos("(", Value) = 0) and (Pos(")", Value)=0) then
begin
Result.Name := _Value;
EXIT;
end;

{Определяем кол-во параметров}

ZapCount{Количесво запятых} := GetCharCount(",", Value);


{Если параметров нет, то выход}
if ZapCount = 0 then EXIT;


{Задаем длину массива параметров}
SetLength(Result.Params, ZapCount+1);
//SetLength(Params, ZapCount+1);


{Заполнение массива параметров значениями}

delete(Value, 1, Pos("""", Value)-1);
delete(Value, Pos(")", Value), 1);

for i := 0 to LENGTH(Result.Params) - 1 do
begin
{Поиск значения параметра
Находим первую кавычку и стераем все до нее}

{Убиваем первую кавычку}
delete(Value, POS("""", Value), 1);

{Назначаем значение параметра до следующей ковычки}
Result.Params[i] := COPY(Value, 1, Pos("""", Value)-1) ;//""+inttostr(i);

{Убиваем вторую кавычку}
delete(Value, POS("""", Value), 1);

{Убиваем все до следующей кавычки}
delete(Value, 1, Pos("""", Value)-1);
end;


end;

function FuncToStringLine(Func: TStringFunction): string;
var i: integer;
begin
Result := "";

for i := 0 to LENGTH(Func.Params) - 1 do
if i = LENGTH(Func.Params) - 1 then Result :=Result+ """" + Func.Params[i] + """"
else Result := Result+ """" + Func.Params[i] + """, ";

Result := Func.Name + "(" + Result + ")";

end;

end.



Жду Ваших мнений, господа!


 
gek   (2001-12-27 13:07) [14]

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


 
Snake   (2001-12-27 14:12) [15]

Если это на Дельфях, то можно попробовать поюзать потоки. Правда, скорее всего, в записях нужно будет хранить признак типа этой записи - монитор или комп.


 
VitHouse   (2001-12-27 14:29) [16]

>gek

Вообще-то я попробывал, по моему не плохо!)
Посмотри мыло: там демошка на основе этого скрипта, + файл для этой проги, посмотри структуру и открой её в проге. прога ещё в разработке!
На векторную графику не обращай внимания - отдельный разговор)


 
VaS   (2001-12-27 14:48) [17]

Структурированные хранилища не подойдут?


 
VitHouse   (2001-12-27 15:01) [18]

>VaS

Благодарю за интерес!

А можно по-подробнее...


 
ValeraVV   (2001-12-27 15:26) [19]

Ну если на то пошло, VitHouse © (27.12.01 12:54), используй XML.

Посмотри также мой примерчик, выслал на мыло, hardware.rar, там правда не документ, а база, но типы объектов произвольные (разработчику еще неизвестные, заводимые пользователем)

XML тебе идеально подходит, используй вместо таблиц (как у меня) TClientDataset, и гони их в XML для обмена между пользователями, а руки дойдут - собственный парсер сделать можно, главное с форматом файла "устандартиться"


 
gek   (2001-12-27 15:31) [20]

Неа это по-моему изврат.
Лучше все-таки писать все это дело в типизированном файле.
Ну а если в текстовом, ну на мой взгляд(не претендую на гениальность) все-же лучше с ключом
key,str1,str2(все равно строку надо анализировать)
зачем так много кода?


 
VitHouse   (2001-12-27 16:00) [21]

>ValeraVV © (27.12.01 15:26

Спасибо за совет, как посмотрю отвечу


 
perov   (2001-12-27 16:03) [22]

в Турбо Паскале 5,5 был и есть хороший пример хранения данных разных типов с помощью потоков (небольшая БД). На основе этой демки я даже написал очень даже неплохую программульку


 
ValeraVV   (2001-12-27 17:07) [23]

>VitHouse © (27.12.01 16:00)
Поясню идею
Откажись от древовидной структуры (делай не как у меня)
Откажись от интерфейсов (интерфейсы у меня нужны лишь для того, чтобы отражать сходства между объектами разных типов)
Тогда у тебя:
ClientDataSet1 (ObjID, ObjName, ObjAttrs)- список объектов, у него есть поле ObjAttrs типа ftDataSet, то есть дочерняя таблица, к ней привязываешь
ClientDataSet2 - перечень атрибутов со значениями AttrName, AttrValue (можно все типа String)
Заполнил базу - скинул файл ClientDataSet1.SaveToFile(const FileName: string = ""; Format: TDataPacketFormat = dfBinary), если укажешь Format=dfXML или расширение ".xml", тогда все скинется в XML - тогда потом можно свой парсер применять.
В D6 вроде как можно по-приличней оформленные XML получать, я еще не смотрел.
У другого юзера делай ClientDataSet1.LoadFromFile(const FileName: string = "");


 
ValeraVV   (2001-12-27 17:30) [24]

Точно, в D6, XML поприличней, только что попробовал на своей базе в дезайн-тайме - красиво получается


 
ValeraVV   (2001-12-27 18:33) [25]

>VitHouse © (27.12.01 16:00)
К чему пришел?
еще идея (вообще изврат)
TMonitor = class(TComponent)
published
Name: string;
ModelNo: integer;
end;
TMonitorSuper=class(TMonitor)
published
ExtraParameter:string;
end;


Создавай объекты так:
TMonitor.Create(DataModule1);
TMonitorSuper.Create(DataModule1);
перебирай через DataModule1.Components
потом делай TFileStream.WriteComponent(DataModule1), а чтобы сделать файл читаемым (и редактируемым в блокноте)используй ObjectBinaryToText и ObjectTextToBinary

Короче и XML и WriteComponent используют встроенные методы чтения/сохранения.
Может легче, научиться работать с потоками?


 
ValeraVV   (2001-12-27 18:39) [26]

Забыл, чтобы WriteComponent и ReadComponent работали надо RegisterClass(TMonitor), RegisterClass(TMonitorSuper) делать


 
3d[Power]   (2001-12-28 01:45) [27]

Кстати люди я столкнулся с такой же проблемой!
Вот к примеру у меня есть:

MyBrick = record
x,y : word;
texture : byte;
animated : boolean;
...
end;


Я допустим пишу это все в файл , и получается 1 record у меня занимает, скока, 4 байта(или 5). Вот если я запишу допустим 10 раз это все это будет 40 байт. А после этого мне надо воткнуть вот что:

TMySTRData = record
string1 : shortstring;
value : single;
parameter : byte;
end;


1 раз и затем снова продолжать писать TMyBrick много раз.

Решение номер 1:
Объединить record TMySTRData и TMyBrick. Но это тогда огромная потеря места!.

Решение номер 2:
Создать свой обработчик файла который через blockread будет все это обрабатывать. Допустим:

Байты нового якобы record"a:
$00 - тип записи (если 1 то TMyBrick а 2 TMySTRDATA)
И потом в зависимости от типа записи считывать определенное колво байт.

Вопрос вот вчем:
Можно ли так сделать:
К примеру myfile.seek(someaddr)
а потом read(myfile, mybrick);
или read(myfile, mystrdata);

А приходится указывать myfile : file of TMYBRICK.


 
ValeraVV   (2001-12-28 06:10) [28]

>3d[Power] © (28.12.01 01:45)
В Дельфи/Паскале, конструкция myfile : file of TMYBRICK, введена в язык для того, чтобы делать:
1.seek(3), вместо seek(3* SizeOf(TMYBRICK)),
2.read(mybrick), вместо blockread(mybrick, SizeOf(TMYBRICK)),
3.write(mybrick), вместо blockwrite(mybrick, SizeOf(TMYBRICK)),
Все, 3 пункта, и больше ничего из этого не выжать, заметь, что везде подставляется SizeOf(TMYBRICK), взятый из объявления myfile (а откуда еще знать какой же все таки размер переменной).
Если нужно пользоваться возможностями "встроенными" в Delphi, то пользуйтесь VCL Streaming System - это когда Delphi сама способна сохранять/загружать объекты зарегистрированных классов (без override методов, по умолчанию, сохраняются published свойства объектов), заботиться практически ни о чем не надо - если такая цель стоит. (см. ValeraVV © (27.12.01 18:33))


 
VitHouse   (2001-12-28 06:59) [29]

По моему, стандартные решения Дельфи этой проблемы здесь не подайдут!А вот такой пример записи файла (как HTML)

Monitor(Name="Samsung", Size="17", Class="AA");
Computer(Proc="Pentium IV", MHZ="1400");

При этом сделать новую структуру типу чтения скриптофункции:

TScryptoFunc = record
Name: string;
ArrayOfParamNames: array of string;
ArrayOfValueParams: array of string;
end;


И при чтении строки из скриптофайла создается переменная типа TScryptoFunc
Читаем строку Monitor(Name="Samsung", Size="17", Class="AA");
Получаем

var
ReadSF: TScryptoFunc
begin
ReadSF := ReadStringToTScryptoFunc( "Monitor(Name="Samsung", Size="17", Class="AA");");
//получаем
ReadSF.Name = "Monitor";
ReadSF.ArrayOfParamNames = ("Name", "Size", Class);
ReadSF.ArrayOfValueParams = ("Samsung", "17", "AA");


Ну и вроде работает.
Потом Сструктуру TScryptoFunc переганять в свои массивы:

case ReadSF.Name of
"Moniror": AddMonitor(ReadSF);
"Computer": AddComputer(ReadSF);
end;


А там дело указателей к элементам)
Далее, строгая структура (типа таблиц),и корректное сохранение в файл.

Жду мнений)





 
3d[Power]   (2001-12-28 07:27) [30]

2 VitHouse & ValeraVV
В таком случае можно самому написать обработчик файла, как я уже предлагал:
1 байт - тип "якобы" record
2 word - скока байт, до следущего seek.

А предложение ReadStringToTScryptoFunc("Monitor(Name="Samsung", Size="17", Class="AA");"); по моему вообще не рациональное, только круто что мона будет самому все в бреде писать.

2 ValeraVV
>1.seek(3), вместо seek(3*SizeOf(TMYBRICK)),
>2.read(mybrick), вместо blockread(mybrick,SizeOf(TMYBRICK)),
>3.write(mybrick), вместо blockwrite(mybrick,SizeOf(TMYBRICK)),
Только в этом случае дельфа сама "расставляет" байты по переменным. а




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

Форум: "Основная";
Текущий архив: 2002.01.17;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.68 MB
Время: 0.047 c
3-52500
dron1
2001-12-15 17:25
2002.01.17
как связать таблицы


1-52600
Romul
2001-12-29 17:10
2002.01.17
Вопрос по TThread


1-52545
Smok_er
2001-12-28 05:37
2002.01.17
Exception EJPEG


1-52542
AVL
2001-12-21 11:32
2002.01.17
Вопрос по FastReport 4.2


1-52557
AlexBel
2001-12-28 13:12
2002.01.17
Перемещение фокуса между компонентами





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