Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2012.01.15;
Скачать: CL | DM;

Вниз

Сохранение в файл большого количества картинок и данных   Найти похожие ветки 

 
igorium ©   (2011-10-07 09:08) [0]

Всем привет.
Имеется record в котором 20 полей (integer и string), 3 динамических массива (integer) и картинка.

Имеется переменная, которая является динамическим массивом моего record"а.
Все картинки будут одного размера, если это поможет.
Задача сохранить весь динамический массив в файл, а потом этот файл прочитать.

Как это дело реализовать?
Заранее благодарен.


 
Дмитрий Белькевич   (2011-10-07 09:15) [1]

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


 
Юрий Зотов ©   (2011-10-07 09:26) [2]

При сохранении данных произвольного размера общий подход такой - сначала пишется их размер, затем сами данные.

Сначала напишите процедуру сохранения одного рекорда и в ней используйте этот способ при записи:
- каждой строки
- каждого массива
- картинки

Потом по тому же принципу напишите процедуру сохранения всего массива рекордов.

Чтение такое: сначала читаем длину данных, потом сами данные.


 
sniknik ©   (2011-10-07 09:44) [3]

> Как это дело реализовать?
как все абстрактное - никак.

p.s. посоветовал бы из рекорда сделать запись рекордсета, и хранить их список (большое количество картинок и данных) в рекордсете, да по опыту знаю бесполезно... свой велосипед всегда ближе к телу...


 
Ega23 ©   (2011-10-07 10:06) [4]

Раз Delphi 7 и в рекордах методов объявлять низя, то:
вместо массива - список, вместо рекорда - класс + метод SaveToStream


 
Очень Злой   (2011-10-07 11:26) [5]


> Как это дело реализовать?


Ну может это чем-нить поможет:
http://delphimaster.net/view/2-1317305480/

Или уже моя реализация в качестве примера:
Я пишу локальный чат и в серверной части сохранение и загрузку данных об юзерах реализовал так (там тоже есть динамические массивы в динамическом массиве):

//************************************************************************//
//          Описание типов данных и вспомогательные функции               //
//************************************************************************//

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.


Может и не лучший способ, но работает нормально...


 
DVM ©   (2011-10-07 13:24) [6]


> igorium ©   (07.10.11 09:08) 
> Всем привет.
> Имеется record в котором 20 полей (integer и string), 3
> динамических массива (integer) и картинка.
>
> Имеется переменная, которая является динамическим массивом
> моего record"а.
> Все картинки будут одного размера, если это поможет.
> Задача сохранить весь динамический массив в файл, а потом
> этот файл прочитать.
>

Я бы переделал Record в класс, в котором определил методы
SaveToStream и LoadFromStream, внутри которых использовал бы TWriter и TReader соответственно для сохранения своих полей.


 
Медвежонок Пятачок ©   (2011-10-07 13:27) [7]

а я бы убрал бы и рекорд и класс.
и не напоролся бы на ситуацию старого файла и новых рекорда/ридера etc


 
Омлет ©   (2011-10-07 13:31) [8]

> Медвежонок Пятачок ©   (07.10.11 13:27) [7]

Просто нужно поле с номером версии формата )


 
DVM ©   (2011-10-07 13:32) [9]


> 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 и все станут сохранят по другому данные.


 
DVM ©   (2011-10-07 13:33) [10]


> Медвежонок Пятачок ©   (07.10.11 13:27) [7]


> и не напоролся бы на ситуацию старого файла и новых рекорда/ридера
> etc

Это не проблема, решается введение полей с версией и маркером, так в той же Delphi сделано.


 
DVM ©   (2011-10-07 13:36) [11]


> Медвежонок Пятачок ©   (07.10.11 13:27) [7]
> а я бы убрал бы и рекорд и класс.

И сохранял в XML :). Кстати, это не проблема, надо лишь написать наследника TReader и TWriter, сохраняющего поля в XML.


 
Медвежонок Пятачок ©   (2011-10-07 13:40) [12]

Это не проблема, решается введение полей с версией и маркером, так в той же Delphi сделано.

этого мало.
нужно во всех последующих версиях тащить необходимым хламом старые версии ридера/райтера и их диспетчер.

в то время как есть простой и понятный load у xml. на все версии.


 
Дмитрий Белькевич   (2011-10-07 13:48) [13]


> И сохранял в XML :). Кстати, это не проблема, надо лишь
> написать наследника TReader и TWriter, сохраняющего поля
> в XML.


В XML бинарник?


 
Юрий Зотов ©   (2011-10-07 13:50) [14]

Куча картинок, сохраненная в XML.... или в любом другом текстовом формате...

...сколько весить будет?
:o)


 
Юрий Зотов ©   (2011-10-07 13:53) [15]


> Дмитрий Белькевич   (07.10.11 13:48) [13]
> В XML бинарник?

Само по себе - не вопрос (побайтно пишем 16-ричное представление, да и все дела). Но размер...


 
Медвежонок Пятачок ©   (2011-10-07 13:59) [16]

а сколько будет весить куча картинок сама по себе?

пс
вы никогда фотки по почте не пересылали?
base64 и увеличение объема в 4/3 раза

ппс какие-то бородатые детские страхи....


 
Медвежонок Пятачок ©   (2011-10-07 14:03) [17]

я бы лучше задался вопросом - а зачем вообще совать какие-то файлы в файл.


 
igorium ©   (2011-10-07 15:16) [18]


> Медвежонок Пятачок ©   (07.10.11 14:03) [17]
> я бы лучше задался вопросом - а зачем вообще совать какие-
> то файлы в файл.


Ну надо мне и все.
Есть большая форма, на которой я создаю динамические массива и панели.
В каждой панели картинка, которую пользователь сам выберет.
Получается определенное художество.
И делаю банальную функцию SAVE, чтобы все сохранить.
А для того, чтобы все сохранилось и в следующей раз все выводилось надо сохранить кучу данных и картинок.

Пока в голове следующая идея из компиляции ваших и не ваших советов:
1) Разделить сохранение данных и сохранение картинок (что очень не хочется).
2) Сохранить данные как советовал Юрий Зотов.
Честно говоря ни разу еще не сохранял в НЕ_текстовый файл. Пока слабо представляю реализацию, но думаю в интернете найду (если вы подскажите будет еще лучше).
3) Создать и сохранить огромный Битмап. Его высота = высоте любой картинки, а ширина = сумма ширин всех картинок.
4) В итоге получится 2 файла - с данными и с картинками.
Причем пользователь сможет посмотреть файл с картинками, что не очень нравится. Так же считаю не идеальным хранить 2 файла для каждого сохранения, а не один...


 
b z   (2011-10-07 15:19) [19]

Ну вот офисные документы, чем не пример?


 
stas ©   (2011-10-07 15:25) [20]


> Честно говоря ни разу еще не сохранял в НЕ_текстовый файл.
>  Пока слабо представляю реализацию, но думаю в интернете
> найду (если вы подскажите будет еще лучше).


Ключевое слово TStream
Уже об этом писал и - Ega23 ©   (07.10.11 10:06) [4]


 
Игорь Шевченко ©   (2011-10-07 15:25) [21]


> И делаю банальную функцию SAVE, чтобы все сохранить.


Сохраняй форму в DFM


 
igorium ©   (2011-10-07 15:33) [22]


> Игорь Шевченко ©   (07.10.11 15:25) [21]

> > И делаю банальную функцию SAVE, чтобы все сохранить.
>
> Сохраняй форму в DFM


Не знал, что можно сохранить в DFM и потом прочитать его (как я понял это формат формы Дельфи).

Но мне это не подойдет, т.к. тогда полученный файл я не смогу редактировать.
Самое главное - это мой рекорд. Из него я смогу сделать новые панели, а из созданных панелей рекорд я уже не восстановлю :(


 
Игорь Шевченко ©   (2011-10-07 16:24) [23]


> Но мне это не подойдет, т.к. тогда полученный файл я не
> смогу редактировать.


Почему не сможешь ? Загрузи и будет тебе форма


 
igorium ©   (2011-10-07 17:18) [24]


> Игорь Шевченко ©   (07.10.11 16:24) [23]
>
> > Но мне это не подойдет, т.к. тогда полученный файл я не
>
> > смогу редактировать.
>
> Почему не сможешь ? Загрузи и будет тебе форма


Как в форму DFM динамически загрузить ~50-100 рекордов, каждый из которых состоит из 20 полей (integer и string), 3 динамических массивов (integer) и картинки.

Это реально???
Тогда где можно поподробнее почитать про это?


 
Игорь Шевченко ©   (2011-10-07 17:24) [25]


> Тогда где можно поподробнее почитать про это?


в classes.pas можно почитать. Начиная с методов TStream.ReadComponent, TStream.WriteComponent


 
DVM ©   (2011-10-07 17:38) [26]


> igorium ©  

Вот тут Gunsmoker http://www.gunsmoker.ru/2011/08/blog-post.html как раз начал серию статей про сериализацию. Как раз для тебя. Правда там пока только начало.


 
Rouse_ ©   (2011-10-07 23:32) [27]


> Медвежонок Пятачок ©   (07.10.11 14:03) [17]
>
> я бы лучше задался вопросом - а зачем вообще совать какие-
> то файлы в файл.

Этот вопрос лучше сразу перенаправить в MS, ибо как раз вопрос о IStorage концепции, а если вспомнить что на базе IStorage понаделано...


 
sniknik ©   (2011-10-08 10:51) [28]

сравнивать концепцию MS с их файлами-заменами прямого доступа к диску, и "местный" последовательный вариант аналог текстового файла только другими фалами вместо строк.... как то даже глупо.

> В XML бинарник?
не проблема если размер не волнует (а и не должен бы). + в варианте рекордсета (ADO) сохранять можно как "xml" так и в бинарном виде, размер будет меньше чем у xml, но больше чем при записи сериализации.


 
_Юрий   (2011-10-08 11:22) [29]

Все способы имеют недостатки:
Бинарный стриминг - зависимость от версии
TReader\TWriter - а вот что будет, если мы переименуем свойство?
XML - размер и скорость чтения

по нынешним временам наверно лучше все таки XML, мощности позволяют, а удобство налицо


 
DVM ©   (2011-10-08 14:31) [30]


> _Юрий   (08.10.11 11:22) [29]


> TReader\TWriter - а вот что будет, если мы переименуем свойство?

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


 
igorium ©   (2011-10-08 16:19) [31]


> sniknik ©   (07.10.11 09:44) [3]
> p.s. посоветовал бы из рекорда сделать запись рекордсета,
>  и хранить их список (большое количество картинок и данных)
> в рекордсете, да по опыту знаю бесполезно... свой велосипед
> всегда ближе к телу...


Где можно подробно прочитать про Рекордсет?
Сам я первый раз слышу такое название.


 
Anatoly Podgoretsky ©   (2011-10-08 17:28) [32]

> igorium  (08.10.2011 16:19:31)  [31]

АДО


 
Дмитрий Белькевич   (2011-10-09 10:04) [33]

Посмотри еще это:

IStorage

http://msdn.microsoft.com/en-us/library/windows/desktop/aa380015(v=vs.85).aspx


 
Дмитрий Белькевич   (2011-10-09 10:09) [34]

http://www.google.com/codesearch#search/&q=IStorage%20lang:%5Epascal$&type=cs



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

Текущий архив: 2012.01.15;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.008 c
15-1317134857
PreDatoR
2011-09-27 18:47
2012.01.15
Ваши партии с шахматными движками.


6-1218309025
Doc.X
2008-08-09 23:10
2012.01.15
Регестарция в WordPress


15-1316959585
Pit
2011-09-25 18:06
2012.01.15
Несколько вопросов по Android


2-1317904913
Alex_C
2011-10-06 16:41
2012.01.15
Узнать, нажата ли кнопка на мыши


15-1317155402
Юрий
2011-09-28 00:30
2012.01.15
С днем рождения ! 28 сентября 2011 среда