Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Сохранение в файл большого количества картинок и данных [D7, XP]


Страницы:   1 2

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]

Так как почти все динамическое, то ручками поэлементно. Файлу придумать какую-нибудь структуру, что бы позже можно было прочитать.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо