![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Сохранение в файл большого количества картинок и данных [D7, XP]
igorium © (2011-10-07 09:08:00)Всем привет.
Имеется record в котором 20 полей (integer и string), 3 динамических массива (integer) и картинка.
Имеется переменная, которая является динамическим массивом моего record'а.
Все картинки будут одного размера, если это поможет.
Задача сохранить весь динамический массив в файл, а потом этот файл прочитать.
Как это дело реализовать?
Заранее благодарен.
Юрий Зотов (2011-10-07 13:50:00) [21]Куча картинок, сохраненная в XML.... или в любом другом текстовом формате...
...сколько весить будет?
:o)
Дмитрий Белькевич (2011-10-07 13:48:00) [22]
> И сохранял в XML :). Кстати, это не проблема, надо лишь
> написать наследника TReader и TWriter, сохраняющего поля
> в XML.
В XML бинарник?
Медвежонок Пятачок (2011-10-07 13:40:00) [23]Это не проблема, решается введение полей с версией и маркером, так в той же Delphi сделано.
этого мало.
нужно во всех последующих версиях тащить необходимым хламом старые версии ридера/райтера и их диспетчер.
в то время как есть простой и понятный load у xml. на все версии.
DVM (2011-10-07 13:36:00) [24]
> Медвежонок Пятачок © (07.10.11 13:27) [7]
> а я бы убрал бы и рекорд и класс.
И сохранял в XML :). Кстати, это не проблема, надо лишь написать наследника TReader и TWriter, сохраняющего поля в XML.
DVM (2011-10-07 13:33:00) [25]
> Медвежонок Пятачок © (07.10.11 13:27) [7]
> и не напоролся бы на ситуацию старого файла и новых рекорда/ридера
> etc
Это не проблема, решается введение полей с версией и маркером, так в той же Delphi сделано.
DVM (2011-10-07 13:32:00) [26]
> DVM © (07.10.11 13:24) [6]
Или даже так:
TBaseStreamedObject = class(TPersistent)
strict protected
procedure ReadData(Reader : TReader); virtual; abstract;
procedure WriteData(Writer : TWriter); virtual; abstract;
procedure SaveToStream(Stream : TStream); virtual; abstract;
procedure LoadFromStream(Stream : TStream); virtual; abstract;
procedure SaveToFile(FileName : string); virtual; abstract;
procedure LoadFromFile(FileName : string); virtual; abstract;
end;
TStreamedObject = class(TBaseStreamedObject)
public
procedure SaveToStream(Stream : TStream); override;
procedure LoadFromStream(Stream : TStream); override;
procedure SaveToFile(FileName : string); override;
procedure LoadFromFile(FileName : string); override;
end;
...
////////////////////////////////////////////////////////////////////////////////
// TStreamedObject
////////////////////////////////////////////////////////////////////////////////
procedure TStreamedObject.LoadFromStream(Stream: TStream);
var
Reader: TReader;
begin
Reader := TReader.Create(Stream, $FF);
try
ReadData(Reader);
finally
FreeAndNil(Reader);
end;
end;
//------------------------------------------------------------------------------
procedure TStreamedObject.SaveToStream(Stream: TStream);
var
Writer: TWriter;
begin
Writer := TWriter.Create(Stream, $FF);
try
WriteData(Writer);
finally
FreeAndNil(Writer);
end;
end;
//------------------------------------------------------------------------------
procedure TStreamedObject.SaveToFile(FileName : string);
var
Stream: TFileStream;
begin
Stream := TFileStream.Create(FileName, fmCreate);
try
SaveToStream(Stream);
finally
Stream.Free;
end;
end;
//------------------------------------------------------------------------------
procedure TStreamedObject.LoadFromFile(FileName : string);
var
Stream: TFileStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead);
try
LoadFromStream(Stream);
finally
Stream.Free;
end;
end;
Все объекты в программе наследуем от TStreamedObject и перенкрываем в них ReadData и WriteData.
При таком подходе при необходимости, можно будет поменять тип TWriter и TReader на их наследника сохраняющего данные по другому в классе TStreamedObject и все станут сохранят по другому данные.
Омлет (2011-10-07 13:31:00) [27]> Медвежонок Пятачок © (07.10.11 13:27) [7]
Просто нужно поле с номером версии формата )
Медвежонок Пятачок (2011-10-07 13:27:00) [28]а я бы убрал бы и рекорд и класс.
и не напоролся бы на ситуацию старого файла и новых рекорда/ридера etc
DVM (2011-10-07 13:24:00) [29]
> igorium © (07.10.11 09:08)
> Всем привет.
> Имеется record в котором 20 полей (integer и string), 3
> динамических массива (integer) и картинка.
>
> Имеется переменная, которая является динамическим массивом
> моего record'а.
> Все картинки будут одного размера, если это поможет.
> Задача сохранить весь динамический массив в файл, а потом
> этот файл прочитать.
>
Я бы переделал Record в класс, в котором определил методы
SaveToStream и LoadFromStream, внутри которых использовал бы TWriter и TReader соответственно для сохранения своих полей.
Очень Злой (2011-10-07 11:26:00) [30]
> Как это дело реализовать?
Ну может это чем-нить поможет:
http://delphimaster.ru/cgi-bin/forum.pl?id=1317305480&n=18
Или уже моя реализация в качестве примера:
Я пишу локальный чат и в серверной части сохранение и загрузку данных об юзерах реализовал так (там тоже есть динамические массивы в динамическом массиве):
//************************************************************************//
// Описание типов данных и вспомогательные функции //
//************************************************************************//
unit addfunc;
interface
uses classes, sysutils, zlib;
procedure UsersDataSave(filename:string);
procedure UsersDataLoad(filename:string);
...
type Tpassline = packed array[1..8] of char;
...
type
TUserData = packed record
Uin:Cardinal; // идентификатор юзера или канала
Nick:string[16]; // ник юзера или название канала
IsChanel: byte; // 0 - Пользователь, 1 - публичный канал, 2-приватный канал (подписка только по приглашению)
last_auth_time:TDateTime; // дата последней авторизации для юзера или дата создания канала
FullName:string[50]; // полное имя юзера или описание канала
case boolean of
false: (password:TPassLine); //пароль юзера
true: (founder:cardinal; // Создатель канала
res:cardinal); //Пока резерв, хз, может понадобится
end;
type
TUinRec = cardinal;
type
TUinList = packed array of TUinRec;
type
TUser=packed record
UserData:TUserData;
Contacts: TUinList; //для юзеров - список контактов, для канала - список подписанных
end;
type TUserList=packed array of TUser;
var
UserList:TUserList;
MaxUid:cardinal=1000;
...
implementation
// Cохранение данных массива в файл с компресией
procedure UsersDataSave(filename:string);
var
fstream:TFileStream;
LenArray, LenSubArray, i:integer;
begin
fStream:=TFileStream.Create(filename,fmCreate);
try
with TCompressionStream.Create(clMax,fstream) do
try
WriteBuffer(MaxUid,sizeof(MaxUid));
lenArray:=length(UserList);
WriteBuffer(lenarray,sizeof(lenarray));
for i:=0 to lenarray-1 do
begin
WriteBuffer(UserList[i].UserData,sizeof(TUserdata));
LenSubArray:=Length(UserList[i].Contacts);
WriteBuffer(LenSubArray,sizeof(LenSubArray));
WriteBuffer(UserList[i].Contacts[0],LenSubArray*sizeof(UserList[i].Contacts[0])) ;
end;
finally
Free;
end;
finally
fstream.free;
end;
end;
// Загрузка данных массива из файла с декомпресией
procedure UsersDataLoad(filename:string);
var
fstream:TFileStream;
lenArray, LenSubArray, i:integer;
begin
fstream:=TFileStream.Create(filename,fmOpenRead or fmShareDenyWrite);
try
with TDecompressionStream.Create(fstream) do
try
ReadBuffer(MaxUid,sizeof(MaxUid));
ReadBuffer(lenarray,sizeof(lenarray));
SetLength(UserList,lenarray);
for i:=0 to lenarray-1 do
begin
ReadBuffer(UserList[i].UserData,sizeof(TUserdata));
ReadBuffer(LenSubArray,sizeof(LenSubArray));
SetLength(Userlist[i].Contacts,LenSubArray);
ReadBuffer(Userlist[i].Contacts[0],LenSubArray*sizeof(Userlist[i].Contacts[0]));
end;
finally
free;
end;
finally
fstream.Free;
end;
end;
...
end.
Может и не лучший способ, но работает нормально...
Ega23 (2011-10-07 10:06:00) [31]Раз Delphi 7 и в рекордах методов объявлять низя, то:
вместо массива - список, вместо рекорда - класс + метод SaveToStream
sniknik (2011-10-07 09:44:00) [32]> Как это дело реализовать?
как все абстрактное - никак.
p.s. посоветовал бы из рекорда сделать запись рекордсета, и хранить их список (большое количество картинок и данных) в рекордсете, да по опыту знаю бесполезно... свой велосипед всегда ближе к телу...
Юрий Зотов (2011-10-07 09:26:00) [33]При сохранении данных произвольного размера общий подход такой - сначала пишется их размер, затем сами данные.
Сначала напишите процедуру сохранения одного рекорда и в ней используйте этот способ при записи:
- каждой строки
- каждого массива
- картинки
Потом по тому же принципу напишите процедуру сохранения всего массива рекордов.
Чтение такое: сначала читаем длину данных, потом сами данные.
Дмитрий Белькевич (2011-10-07 09:15:00) [34]Так как почти все динамическое, то ручками поэлементно. Файлу придумать какую-нибудь структуру, что бы позже можно было прочитать.