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

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.004 c
15-1317473974
Фокс Йожин
2011-10-01 16:59
2012.01.15
Лечение MS SQL. Вопрос знатокам.


8-1221912190
Elz
2008-09-20 16:03
2012.01.15
Помогите найти ошибку в коде


15-1317241802
Юрий
2011-09-29 00:30
2012.01.15
С днем рождения ! 29 сентября 2011 четверг


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


2-1317823891
SergP
2011-10-05 18:11
2012.01.15
Рекурсивное описание классов.





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