![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Сохранение/чтение Объектов TStringLista [D6, Win95/98, WinME, NT4, Win2k, WinXP]
Каспер © (2002-12-26 08:32:00)Народ есть TStringList
Как сохранить список + все его объекты.
Спасибо и с начтупающим!
Каспер (2003-01-05 08:22:00) [1]2 Yuri-7 (05.01.03 07:42)
Сам виноват.. :( надо было все сразу корректно описать.
Есть такая структура
TUserUIN=DWord;
THead = Record // заголовок пакета
CRC:DWord; //4
UIN:TUserUIN; //4
Command:byte;//1
Len:Word; //2 - длина основной части пакета (требуется)
End;
R1=record
x,y:integer;
s:string;
end;
R2=record
z:boolean;
s:string[255];
end;
TPData = Record //основное тело
Case Integer of
0:(User:R1);
1:(Status:R2);
2:(Mess:Rx);
3:(Data:...);
End;
TPacket = Record
Header :THead;
PData :TPData;
end;
!!!-1-!!! дело в том что структура не жесткая (на текущем этапе разработки требуется пока такая, в дальнейшем она может измениться и расшириться - на данные уже сохраненные по барабану, а вот на сам код модуля кторый зависит от этой стуктуры. Просто не хотелось бы его 50 раз переписывать)
Далее вступает в действие модуль Стек (разрабатывается для хранения получаемой из сети информации правильнее назвать его очередь... ). Пришел пакет. Я его запихиваю в стринглист (в Строку-UIN из пакета а в объект само тело). Ну и все остальные пакеты таким же образом дальше. Когда то (не обязательно сначала или с конца, возможно из середины пакеты будут уничтожаться).
Хотелось бы его исользовать таким образом....
В программе описал
var
Очередь:TStack;
begin
Очередь:=Tsack.Create(имя файла где она будет храниться при закрытии проги если она(очередь) не оказалась пуста)
....
end;
ну и пришел пакет, я его обрабатываю сам, как мне надо,
потом типа Очередь.AddPacket(MyPacket), он добавляет в Строку UIN из пакета, а все тело кидает в объект
Сохранить - сохраняет все в файл как есть...
В общем примерно так... :( Сори за сбивчивость
Yuri-7 (2003-01-05 07:42:00) [2]Что-то все сложно у вас получилось. Если нет предубеждения на использование дополнительных компонентов, то для такого случая хорошо подойдет TkbmMemTable. Он не требует BDE и "плотно" хранит string данные. И длину string отдельно не надо хранить.
1. создаешь таблицу
2. объявляешь поля:
with kbm.fielddefs do
begin
Add("x",ftinteger);
Add("y",ftinteger);
Add("S",ftString,32000); или Add("S",ftMemo,1);
end;
CreateTable;
3. Записываешь данные, как в обычную таблицу
4. Сохраняешь, используя kbm.SaveToBinaryFile(..
Каспер (2003-01-05 06:55:00) [3]Спасибо большое...
Хоть и с опозданием но сами понимаете. Новый год штука длинная.
Сам только узнал что 5 число :).
Вы вот разъяснили все. А в инете где нить есть еще примерчики или дока... можно по англицки. Нужно в самообразовательных целях.
С новым годом!
С наступающим рождеством!
Ох...
Юрий Зотов (2002-12-27 16:50:00) [4]1. SaveToStream используется при записи в любой поток (например, в файл), а WriteRecords использует IDE при сохранении формы.
2. > Не вижу соответствия строки и принадлежащему ей объекту
При записи объекта сначала пишется его индекс (он же - индекс строки).
Skier (2002-12-27 13:43:00) [5]>Каспер
Writer: TWriter и Reader: TReader это классы, которые использует
Delphi для записи и чтения свойств компонент в файл формы (.dfm)
Через DefineProperties
пользователь "указывает" Delphi как писать и читать из
файла свойства, имеющие пользовательскую, ("хитрую") структуру...
Кроме того через DefineProperties можно писать неопубликованные свойства...
Каспер (2002-12-27 13:30:00) [6]Юрий Зотов © (27.12.02 09:55)
Плищ разъясни что делают 2 метода
procedure TMyStrings.WriteRecords(Writer: TWriter); и
procedure TMyStrings.ReadRecords(Reader: TReader);
и как ты в них определяешь куда писать... Не вижу соответствия строки и принадлежащему ей объекту
Каспер (2002-12-27 11:19:00) [7]А чем отличаются методы
procedure TStack.SaveToStream(Stream: TStream);
procedure TStack.WriteBody(Writer: TWriter);
вернее когда или для чего они используются
Каспер (2002-12-27 10:22:00) [8]МЛИН (просмотрел)! Не перестаю восхищаться.
Юрий Зотов (2002-12-27 09:55:00) [9]Освобождается. Присвоение Records[i] := nil приводит к вызову SetRecords(i, nil).
Каспер (2002-12-27 09:29:00) [10]А интересно...
память из под объектво не освобождается а просто обNILяется :)
или не все так понял...
Каспер (2002-12-27 05:53:00) [11]Люди спасибо огромное сейчас буду учить и осознавать!
рассмотрены будут все замечания и примеры.
Насчет объектов - я дал грубый пример для упрощения ответов.
На самом деле это пока запись. В ней куча полей так сказать Заголовок -где содержиться CRC тела, CMD (команда), Par1
Ну и тело - это набор байт переменной длинны в зависимости от команды.
В дальнейшем возможно это все перерастет в класс.
:(, но спиной чувствую что так и будет.
Терь по примерам научусь.
Всем еще раз спасибо и с наступающим.
Отдельное Спасибо! Юрию Зотову и Skier © за подробные примеры!
Юрий Зотов (2002-12-27 01:49:00) [12]Вот что я тут набросал. Это потомок TStringList, который сам умееет сохранять "прицепленные" к своим строкам записи и в поток, и в DFM. Соответственно, и в файл тоже. Ну и читать, конечно.
Не тестировал (собирался, но спать очень хочется...). Но писал аккуратно, есть шанс, что заработает. Во всяком случае, компилируется "по нулям".
type
PMyRec = ^TMyRec;
TMyRec = record
X: integer;
Y: integer;
LenS: integer; // Хотя можно (и было бы лучше) обойтись без этого поля.
S: string
end;
TMyStrings = class(TStringList)
private
procedure ReadRecords(Reader: TReader);
procedure WriteRecords(Writer: TWriter);
function GetRecords(Index: integer): PMyRec;
procedure SetRecords(Index: integer; const Value: PMyRec);
protected
procedure ClearRecords; dynamic;
procedure DefineProperties(Filer: TFiler); override;
public
destructor Destroy; override;
procedure Clear; override;
procedure Delete(Index: Integer); override;
procedure SaveToStream(Stream: TStream); override;
procedure LoadFromStream(Stream: TStream); override;
property Records[Index: integer]: PMyRec read GetRecords write SetRecords;
end;
procedure TMyStrings.Clear;
begin
BeginUpdate;
try
ClearRecords;
inherited
finally
EndUpdate
end
end;
procedure TMyStrings.ClearRecords;
var
i: integer;
begin
BeginUpdate;
try
for i := Count - 1 downto 0 do Records[i] := nil
finally
EndUpdate
end
end;
procedure TMyStrings.DefineProperties(Filer: TFiler);
begin
inherited;
Filer.DefineProperty("Records", ReadRecords, WriteRecords, Count > 0)
end;
procedure TMyStrings.Delete(Index: Integer);
begin
BeginUpdate;
try
Records[Index] := nil;
inherited
finally
EndUpdate
end
end;
destructor TMyStrings.Destroy;
begin
OnChange := nil;
OnChanging := nil;
ClearRecords;
inherited
end;
function TMyStrings.GetRecords(Index: integer): PMyRec;
begin
Result := PMyRec(Objects[Index])
end;
procedure TMyStrings.LoadFromStream(Stream: TStream);
function ReadString: string;
var
L: integer;
begin
Stream.ReadBuffer(L, SizeOf(L));
SetString(Result, nil, L);
Stream.Read(Pointer(Result)^, L)
end;
var
i: integer;
P: PMyRec;
begin
BeginUpdate;
with Stream do
try
Text := ReadString;
while Position < Size - 1 do
begin
ReadBuffer(i, SizeOf(i));
GetMem(P, SizeOf(TMyRec));
with P^ do
begin
ReadBuffer(X, SizeOf(X));
ReadBuffer(Y, SizeOf(Y));
S := ReadString;
LenS := Length(S)
end;
Records[i] := P
end
finally
EndUpdate
end
end;
procedure TMyStrings.ReadRecords(Reader: TReader);
var
i: integer;
P: PMyRec;
begin
with Reader do
begin
ReadListBegin;
BeginUpdate;
try
ClearRecords;
while not EndOfList do
begin
ReadListBegin;
i := ReadInteger;
GetMem(P, SizeOf(TMyRec));
with P^ do
begin
X := ReadInteger;
Y := ReadInteger;
LenS := ReadInteger;
S := ReadString
end;
Records[i] := P;
ReadListEnd
end
finally
EndUpdate
end;
ReadListEnd
end
end;
procedure TMyStrings.SaveToStream(Stream: TStream);
procedure WriteString(S: string);
var
L: integer;
begin
L := Length(S);
Stream.WriteBuffer(L, SizeOf(L));
Stream.WriteBuffer(Pointer(S)^, L)
end;
var
i: integer;
begin
WriteString(Text);
for i := 0 to Count - 1 do
if Records[i] <> nil then
with Stream, Records[i]^ do
begin
WriteBuffer(i, SizeOf(i));
WriteBuffer(X, SizeOf(X));
WriteBuffer(Y, SizeOf(Y));
WriteString(S)
end
end;
procedure TMyStrings.SetRecords(Index: integer; const Value: PMyRec);
begin
if Records[Index] <> Value then
begin
Changing;
if Records[Index] <> nil then
begin
Records[Index]^.S := "";
Finalize(Records[Index]^);
FreeMem(Records[Index], SizeOf(TMyRec));
end;
Objects[Index] := TObject(Value);
Changed
end
end;
procedure TMyStrings.WriteRecords(Writer: TWriter);
var
i: integer;
begin
with Writer do
begin
WriteListBegin;
for i := 0 to Count - 1 do
if Records[i] <> nil then
with Records[i]^ do
begin
WriteListBegin;
WriteInteger(i);
WriteInteger(X);
WriteInteger(Y);
WriteInteger(LenS);
WriteString(S);
WriteListEnd
end;
WriteListEnd
end
end;
Севостьянов Игорь (2002-12-26 17:16:00) [13]Хотя собственно для упрощения - это лучший выход (я о примере от Skier © (26.12.02 15:54))
Skier (2002-12-26 17:12:00) [14]>Севостьянов Игорь
> Это же класс, а надо record
Да ну ?! :)
Изначально в вопросе автор пишет про объекты....
Севостьянов Игорь (2002-12-26 17:04:00) [15]gek © (26.12.02 15:11)
> тут в принципе можно файл записей сделать и читать все оттуда
Нельзя потому что String у него переменной длины
> Skier © (26.12.02 15:54)
> Примерно так :
>
> TMyObj = class
> private
> x,y : integer;
> S:string;
> end;
Это же класс, а надо record
Skier (2002-12-26 15:54:00) [16]Примерно так :
TMyObj = class
private
x,y : integer;
S:string;
end;
//.........................
procedure TForm1.Button3Click(Sender: TObject);
procedure SaveStrListToFile(AList : TStringList;
const AFileName : String);
var
ii : Integer;
AFileStream : TFileStream;
ALength : Integer;
ACount : Integer;
begin
if (AList = nil) or
(AFileName = EmptyStr) then Exit;
AFileStream := TFileStream.Create(AFileName, fmCreate);
try
ACount := AList.Count;
AFileStream.Write(ACount, SizeOf(Integer));
for ii := 0 to AList.Count - 1 do begin
with TMyObj(AList.Objects[ii]) do begin
AFileStream.Write(x, SizeOf(Integer));
AFileStream.Write(y, SizeOf(Integer));
ALength := Length(S);
AFileStream.Write(ALength, SizeOf(Integer));
AFileStream.Write(Pointer(S)^, ALength);
end; //with
end; //for
finally
FreeAndNil(AFileStream);
end;//try
end; //SaveStrListToFile
procedure LoadStrListFromFile(AList : TStringList;
const AFileName : String);
var
ii : Integer;
AFileStream : TFileStream;
ALength : Integer;
ACount : Integer;
AMyObj : TMyObj;
begin
if (AList = nil) or
(AFileName = EmptyStr) then Exit;
AFileStream := TFileStream.Create(AFileName, fmOpenRead);
try
AFileStream.Read(ACount, SizeOf(Integer));
for ii := 1 to ACount do begin
AMyObj := TMyObj.Create;
AFileStream.Read(AMyObj.x, SizeOf(Integer));
AFileStream.Read(AMyObj.y, SizeOf(Integer));
AFileStream.Read(ALength, SizeOf(Integer));
SetString(AMyObj.S, PChar(nil), ALength);
AFileStream.Read(Pointer(AMyObj.S)^, ALength);
AList.AddObject(AMyObj.S, AMyObj);
end; //for
finally
FreeAndNil(AFileStream);
end;//try
end; //LoadStrListFromFile
var
AList : TStringList;
AMyObj : TMyObj;
ii : Integer;
begin
AList := TStringList.Create;
try
for ii := 1 to 10 do begin
AMyObj := TMyObj.Create;
AMyObj.x := 10;
AMyObj.y := 100;
AMyObj.s := "Hello N = " + IntToStr(ii);
AList.AddObject(AMyObj.s, AMyObj);
end; //for
SaveStrListToFile(AList, "C:\###\111.dat");
for ii := 1 to 10 do AList.Objects[ii - 1].Free;
AList.Clear;
LoadStrListFromFile(AList, "C:\###\111.dat");
for ii := 1 to 10 do AList.Objects[ii - 1].Free;
AList.Clear;
finally
FreeAndNil(AList);
end; //try
end;
gek (2002-12-26 15:11:00) [17]тут в принципе можно файл записей сделать и читать все оттуда
Skier (2002-12-26 14:42:00) [18]>Каспер
1) И где же ты увидел здесь объекты ?!
2) Посмотри как сделаны методы WriteInteger и WriteString
в классе TWriter, должно помочь...
Каспер (2002-12-26 14:31:00) [19]Можно по асе - 70015922 только киньте сразу что по поводу Дельфей...
Каспер (2002-12-26 14:11:00) [20]Млин люди :(
Высношал весь мозг...
Есть у кого нить примеры
Плиз не материте токо.
1 Список из строк ...
2 к каждой строке привязан
MyRec =record
x,y,integer;
LenS:integer; {длина нижеприведенной S}
S:string; {длина разная указана в переменной выше}
end;
Как все это сохранить в файл...
Если кто сможет найти пример как предложил Юрий Зотов вообще цены не будет, но буду рад любому примеру...
Накидайте плиз все кто что может...
Спасибо