Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сохранение нескольких файлов в одном 
:(
    Опции темы
pushok
Дата 13.8.2009, 10:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 92
Регистрация: 7.2.2007

Репутация: нет
Всего: нет



Всем привет.

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

Первым делом думал создавать новую папку и сохранять нужные файлы в ней, но для конечного пользователя это всеравно будет неудобно.
Еще есть мысль сохранять всю нужную мне информацию в одном файле, записывая его по-байтам в определенном формате, но это как вы сами понимаете - гемор = )

Подскажите, может быть в Delphi есть какие-то предусмотренные способы или функции решения этой проблемы. Может быть в Delphi есть функции работы с архивами. Может быть эти проблемы решаются средствами WinAPI.

Заранее спасибо за помощь.
PM ICQ   Вверх
AntonN
Дата 13.8.2009, 10:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 491
Регистрация: 8.8.2006

Репутация: 3
Всего: 18



Цитата

Еще есть мысль сохранять всю нужную мне информацию в одном файле, записывая его по-байтам в определенном формате, но это как вы сами понимаете - гемор = )


ничуть, именно так поступаю когда нужно упаковать скины для программ или что то подобное.
Если потратишь немного времени и разберешься - все будет легко и красиво smile
дял примера небольшой класс который сохраняет несколько Tbitmap (разных размеров, битности) в один файл - http://desksoft.ru/index.php?forum=13&th=110
если приглядеться то битамп перед сохранением в общий файл выгружается в Tstream - _MBit, ну так вот грузи в этот поток все что тебе угодно, хоть EXE, хоть GIF. Только придется в заголовки добавить поле типа string куда запишется название файла smile


--------------------
user posted image
PM MAIL WWW   Вверх
Yanis
Дата 13.8.2009, 11:01 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2937
Регистрация: 9.2.2004
Где: Москва

Репутация: 72
Всего: 111



Товарищи велосипедисты, с исследовательской точки зрения можно, конечно, хранить вообще все файлы хоть в исполняемом файле. С практической же стороны, архивы ZIP очень даже доставляют в случае хранения ресурсов в одном хранилище. И да, pushok, в Delphi есть модуль для поддержки сжатия по алгоритму DEFLATE. Модуль zlib.

Добавлено @ 11:02
http://forum.vingrad.ru/index.php?act=Sear...ib&skipped=

Это сообщение отредактировал(а) Yanis - 13.8.2009, 11:04


--------------------
user posted image *щёлк*
PM MAIL WWW ICQ   Вверх
former
Дата 13.8.2009, 13:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 5
Всего: 17



Вот еще вариант.


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
kemiisto
Дата 13.8.2009, 13:20 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дикий Кот. =^.^=
****
Награды: 1



Профиль
Группа: Участник Клуба
Сообщений: 3292
Регистрация: 29.7.2007

Репутация: 16
Всего: 160



Yanissmile 

Здесь есть толковый компонент для работы с Zip.

Как альтернатива - компонент с говорящим названием Single File Data Storagesmile 


--------------------
PM MAIL WWW GTalk Jabber   Вверх
w03zd8rc
Дата 13.8.2009, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 26.2.2007

Репутация: нет
Всего: нет



собстна можно взять консольную версию винрара (ставится вместе с винраром) и паковать нужные файлы в один архив через консоль (совсем несложно в делфи)
PM MAIL   Вверх
pushok
Дата 16.8.2009, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 92
Регистрация: 7.2.2007

Репутация: нет
Всего: нет



Ребят, пару дней разбирался - ничего не понял.

Вот из какой-то ссылки (что вы давали) вытянул кусок кода по-проще. Работает хорошо, только вот понять как он работает немогу.
С потоками в плохих отношениях = )

Напишите пожалуйста пояснения к некоторым строчкам.

Код

procedure SaveData(const s: String; BinData: TStream; FilePath: String);
var
  FS: TFileStream;
  Len: Integer;
  Len64: Int64;
begin
  FS := TFileStream.Create(FilePath,fmCreate);
  try
    Len := Length(s);
    FS.Write(Len,SizeOf(Integer));   // Вот здесь. Функция Write записывает элемент Len в поток, при этом длина в байтах этого элемента = SizeOf(Integer). Верно??
    FS.Write(s[1],Len);
    Len64 := BinData.Size;
    FS.Write(Len64,SizeOf(Int64));
    FS.CopyFrom(BinData,Len64);   // Здесь в поток FS копируется поток BinData. При этом он добавляется в поток FS ?
  finally
    FS.Free;
  end;
end;

procedure ReadData(var s: String; BinData: TStream; FilePath: String);
var
  FS: TFileStream;
  Len: Integer;
  Len64: Int64;
begin
  FS := TFileStream.Create(FilePath,fmOpenRead);
  try
    FS.Read(Len,SizeOf(Integer));
    SetLength(s,Len);
    FS.Read(s[1],Len);   // Функция Read считывает из потока FS в переменную s[1] элемент длиною в Len байт?? Или он начинает считывать с Len-ого байта все последующие? При этом этот элемент (последовательность байт) удаляется из потока или поток не изменяется?
    FS.Read(Len64,SizeOf(Int64));
    BinData.CopyFrom(FS,Len64);
  finally
    FS.Free;
  end;
end;


И еще алгоритм записи и чтения в один поток двух файлов выглядит так:
Запись
1. Записываем длину первого файла
2. Записываем первый файл
3. Записываем длину второго файла
4. Записываем второй файл

Чтение
1. Считываем длину первого файла
2. Считываем в переменную количество байт равных длине первого файла
3. Считываем длину второго файла
2. Считываем в переменную количество байт равных длине второго файла

Верно?? Если нет, опишите пожалуйста, что-то непонимаю.

Это сообщение отредактировал(а) pushok - 16.8.2009, 12:40
PM ICQ   Вверх
MetalFan
Дата 16.8.2009, 13:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128



pushok, ну да, вроде бы все написано верно. мыслишь правильно. какие-то проблемы с приведенным кодом?

Но видимо у тебя недопонимание работы потоков данных (TStream и его наследников).

Цитата(pushok @  16.8.2009,  12:38 Найти цитируемый пост)
FS.Write(Len,SizeOf(Integer));   // Вот здесь. Функция Write записывает элемент Len в поток, при этом длина в байтах этого элемента = SizeOf(Integer). Верно??

верно.

Добавлено @ 13:47
Цитата(pushok @  16.8.2009,  12:38 Найти цитируемый пост)
FS.CopyFrom(BinData,Len64);   // Здесь в поток FS копируется поток BinData. При этом он добавляется в поток FS ?

хм... странное понимание... здесь в поток FS копируется Len64 байт из потока BinData, при чем  данные в потоке BinData остаются неизменными.

Цитата(pushok @  16.8.2009,  12:38 Найти цитируемый пост)
 FS.Read(s[1],Len);   // Функция Read считывает из потока FS в переменную s[1] элемент длиною в Len байт?? Или он начинает считывать с Len-ого байта все последующие? При этом этот элемент (последовательность байт) удаляется из потока или поток не изменяется?

Да, здесь функция Read читает Len байт по адресу переменной s[1] с текущей позиции(TStream.Position) потока FS. при этом позиция потока FS сдвигается на Len байт. данные в потоке FS при этом никак не изменяются.

Это сообщение отредактировал(а) MetalFan - 16.8.2009, 13:48


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
pushok
Дата 16.8.2009, 20:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 92
Регистрация: 7.2.2007

Репутация: нет
Всего: нет



Ок. С позицией понял. Теперь такой вопрос.

Пытаюсь записать два файла в один, а потом извлечь их.
Процедура записи:
Код

procedure TForm1.Button5Click(Sender: TObject);
var
b:Int64;
f,fs:TFileStream;
begin
fs:=TFileStream.Create('1.dat',fmCreate);
fs.Free;
fs:=TFileStream.Create('1.dat',fmOpenWrite);

f:=TFileStream.Create('ad.txt',fmOpenRead);
b:=f.Size;
fs.Write(b,SizeOf(Int64));
fs.Write(f,b);
f.Free;


f:=TFileStream.Create('ad1.bmp',fmOpenRead);
b:=f.Size;
fs.Write(b,SizeOf(Int64));
fs.Write(f,b);
f.Free;

fs.Free;
end;


Файл '1.dat' появляется но занимает только 1 Кб

Процедура чтения (пробовал также как и записи, но пишит какую-то ошибку, сделал по-другому)
Код

procedure TForm1.Button6Click(Sender: TObject);
var
fs,f:TFileStream;
ft:TMemoryStream;
b:Int64;
begin
fs:=TFileStream.Create('1.dat',fmOpenRead);

f:=TFileStream.Create('00a.txt',fmCreate);
f.Free;
f:=TFileStream.Create('00a.txt',fmOpenWrite);
fs.Read(b,SizeOf(Int64));
fs.Read(ft,b);
f.Write(ft,b);
f.Free;

f:=TFileStream.Create('00b.bmp',fmCreate);
f.Free;
f:=TFileStream.Create('00b.bmp',fmOpenWrite);
fs.Read(b,SizeOf(Int64));
fs.Read(ft,b);
f.Write(ft,b);
f.Free;

fs.Free;
end;


Два файла появляются, но занимают они по 0 Кб каждый и ничего не содержат.

В чем моя ошибка?

(при этом если я второй файл выключаю из работы, т.е. пытаюсь сохранить только один, та же фигня)

Это сообщение отредактировал(а) pushok - 16.8.2009, 20:55
PM ICQ   Вверх
AntonN
Дата 16.8.2009, 21:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 491
Регистрация: 8.8.2006

Репутация: 3
Всего: 18



м/у файловыми потоками сделай fs.CopyFrom(f,fs.Size); но предварительно не забывай задавать размер dest'у и устанавливать позиции (fs.position:=0;)


--------------------
user posted image
PM MAIL WWW   Вверх
kami
Дата 16.8.2009, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Для записи:
вместо 
Цитата(pushok @  16.8.2009,  20:54 Найти цитируемый пост)
fs.Write(f,b);

Код

fs.CopyFrom(f, b); // в данном случае можно и (f, 0). F1 на CopyFrom рулит.

Соответственно - для чтения тоже.

Цитата(pushok @  16.8.2009,  20:54 Найти цитируемый пост)
 пишит какую-то ошибку, сделал по-другому

Вот в этом Ваша ошибка.
Не нужно считать ошибку "какой-то". Ошибка имеет вполне конкретный смысл, конкретное значение, а при запуске под отладчиком (т.е. в Delphi ) - даже конкретную строчку, на которой происходит.
Вот это всё и нужно проанализировать, и если самому непонятна причина ошибки, то все данные по ней - вывести сюда.

Цитата(pushok @  16.8.2009,  20:54 Найти цитируемый пост)

fs.Read(ft,b);
f.Write(ft,b);

Лишние телодвижения.
нужно проще:
Код

f.CopyFrom(fs, b);

PM MAIL WWW   Вверх
pushok
Дата 16.8.2009, 23:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 92
Регистрация: 7.2.2007

Репутация: нет
Всего: нет



Спасибо всем = )))
все работает, вроде все ясно.

CopyFrom тоже указатель двигает, как и Read, верно?
PM ICQ   Вверх
AntonN
Дата 17.8.2009, 00:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 491
Регистрация: 8.8.2006

Репутация: 3
Всего: 18



лучше считать что не двигает и делать все самому smile


--------------------
user posted image
PM MAIL WWW   Вверх
kami
Дата 17.8.2009, 07:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(AntonN @  17.8.2009,  00:28 Найти цитируемый пост)
лучше считать что не двигает и делать все самому

Лучше. так. не. считать.

Добавлено через 2 минуты и 28 секунд
Read и Write перемещают указатель потока.
соответственно - это делают и все их производные - Read|WriteBuffer; CopyFrom и т.д.

Добавлено через 5 минут и 53 секунды
Маленькое примечание:
если есть TFileStream, с доступом fsOpenRead и в него попытаться что-нибудь записать, то ничего записано не будет и указатель соответственно не передвинется.
Недавно потратил 20 минут на поиск этого своего глюка - не хотел файл записываться и все, размер=0 smile
PM MAIL WWW   Вверх
AntonN
Дата 17.8.2009, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 491
Регистрация: 8.8.2006

Репутация: 3
Всего: 18



Цитата

Лучше. так. не. считать.

Почему. лучше. ?


--------------------
user posted image
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1561 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.