Форум: "Начинающим";
Текущий архив: 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