![]() |
Модераторы: Poseidon, Snowy, bems, MetalFan |
![]() ![]() ![]() |
|
pushok |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 92 Регистрация: 7.2.2007 Репутация: нет Всего: нет |
Всем привет.
Пишу программу. Столкнулся с проблемой: есть несколько файлов разного формата (текстовые, графические) нужно сохранять все эти файлы в одном для удобства транспортировки. Никогда с такой проблемой не сталкивался. Первым делом думал создавать новую папку и сохранять нужные файлы в ней, но для конечного пользователя это всеравно будет неудобно. Еще есть мысль сохранять всю нужную мне информацию в одном файле, записывая его по-байтам в определенном формате, но это как вы сами понимаете - гемор = ) Подскажите, может быть в Delphi есть какие-то предусмотренные способы или функции решения этой проблемы. Может быть в Delphi есть функции работы с архивами. Может быть эти проблемы решаются средствами WinAPI. Заранее спасибо за помощь. |
|||
|
||||
AntonN |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 491 Регистрация: 8.8.2006 Репутация: 3 Всего: 18 |
ничуть, именно так поступаю когда нужно упаковать скины для программ или что то подобное. Если потратишь немного времени и разберешься - все будет легко и красиво ![]() дял примера небольшой класс который сохраняет несколько Tbitmap (разных размеров, битности) в один файл - http://desksoft.ru/index.php?forum=13&th=110 если приглядеться то битамп перед сохранением в общий файл выгружается в Tstream - _MBit, ну так вот грузи в этот поток все что тебе угодно, хоть EXE, хоть GIF. Только придется в заголовки добавить поле типа string куда запишется название файла ![]() |
|||
|
||||
Yanis |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 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 |
|||
|
||||
former |
|
|||
![]() MEMS Expert ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1166 Регистрация: 1.3.2006 Где: Россия Репутация: 5 Всего: 17 |
Вот еще вариант.
-------------------- Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами. |
|||
|
||||
kemiisto |
|
|||
![]() Дикий Кот. =^.^= ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Участник Клуба Сообщений: 3292 Регистрация: 29.7.2007 Репутация: 16 Всего: 160 |
Yanis,
![]() Здесь есть толковый компонент для работы с Zip. Как альтернатива - компонент с говорящим названием Single File Data Storage. ![]() -------------------- |
|||
|
||||
w03zd8rc |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 128 Регистрация: 26.2.2007 Репутация: нет Всего: нет |
собстна можно взять консольную версию винрара (ставится вместе с винраром) и паковать нужные файлы в один архив через консоль (совсем несложно в делфи)
|
|||
|
||||
pushok |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 92 Регистрация: 7.2.2007 Репутация: нет Всего: нет |
Ребят, пару дней разбирался - ничего не понял.
Вот из какой-то ссылки (что вы давали) вытянул кусок кода по-проще. Работает хорошо, только вот понять как он работает немогу. С потоками в плохих отношениях = ) Напишите пожалуйста пояснения к некоторым строчкам.
И еще алгоритм записи и чтения в один поток двух файлов выглядит так: Запись 1. Записываем длину первого файла 2. Записываем первый файл 3. Записываем длину второго файла 4. Записываем второй файл Чтение 1. Считываем длину первого файла 2. Считываем в переменную количество байт равных длине первого файла 3. Считываем длину второго файла 2. Считываем в переменную количество байт равных длине второго файла Верно?? Если нет, опишите пожалуйста, что-то непонимаю. Это сообщение отредактировал(а) pushok - 16.8.2009, 12:40 |
|||
|
||||
MetalFan |
|
||||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 62 Всего: 128 |
pushok, ну да, вроде бы все написано верно. мыслишь правильно. какие-то проблемы с приведенным кодом?
Но видимо у тебя недопонимание работы потоков данных (TStream и его наследников).
верно. Добавлено @ 13:47
хм... странное понимание... здесь в поток FS копируется Len64 байт из потока BinData, при чем данные в потоке BinData остаются неизменными. Да, здесь функция Read читает Len байт по адресу переменной s[1] с текущей позиции(TStream.Position) потока FS. при этом позиция потока FS сдвигается на Len байт. данные в потоке FS при этом никак не изменяются. Это сообщение отредактировал(а) MetalFan - 16.8.2009, 13:48 -------------------- There are always someone smarter than you... |
||||
|
|||||
pushok |
|
||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 92 Регистрация: 7.2.2007 Репутация: нет Всего: нет |
Ок. С позицией понял. Теперь такой вопрос.
Пытаюсь записать два файла в один, а потом извлечь их. Процедура записи:
Файл '1.dat' появляется но занимает только 1 Кб Процедура чтения (пробовал также как и записи, но пишит какую-то ошибку, сделал по-другому)
Два файла появляются, но занимают они по 0 Кб каждый и ничего не содержат. В чем моя ошибка? (при этом если я второй файл выключаю из работы, т.е. пытаюсь сохранить только один, та же фигня) Это сообщение отредактировал(а) pushok - 16.8.2009, 20:55 |
||||
|
|||||
AntonN |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 491 Регистрация: 8.8.2006 Репутация: 3 Всего: 18 |
м/у файловыми потоками сделай fs.CopyFrom(f,fs.Size); но предварительно не забывай задавать размер dest'у и устанавливать позиции (fs.position:=0;)
|
|||
|
||||
kami |
|
||||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 23 Всего: 72 |
Для записи:
вместо
Соответственно - для чтения тоже. Вот в этом Ваша ошибка. Не нужно считать ошибку "какой-то". Ошибка имеет вполне конкретный смысл, конкретное значение, а при запуске под отладчиком (т.е. в Delphi ) - даже конкретную строчку, на которой происходит. Вот это всё и нужно проанализировать, и если самому непонятна причина ошибки, то все данные по ней - вывести сюда. Лишние телодвижения. нужно проще:
|
||||
|
|||||
pushok |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 92 Регистрация: 7.2.2007 Репутация: нет Всего: нет |
Спасибо всем = )))
все работает, вроде все ясно. CopyFrom тоже указатель двигает, как и Read, верно? |
|||
|
||||
AntonN |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 491 Регистрация: 8.8.2006 Репутация: 3 Всего: 18 |
лучше считать что не двигает и делать все самому
![]() |
|||
|
||||
kami |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 23 Всего: 72 |
Лучше. так. не. считать. Добавлено через 2 минуты и 28 секунд Read и Write перемещают указатель потока. соответственно - это делают и все их производные - Read|WriteBuffer; CopyFrom и т.д. Добавлено через 5 минут и 53 секунды Маленькое примечание: если есть TFileStream, с доступом fsOpenRead и в него попытаться что-нибудь записать, то ничего записано не будет и указатель соответственно не передвинется. Недавно потратил 20 минут на поиск этого своего глюка - не хотел файл записываться и все, размер=0 ![]() |
|||
|
||||
AntonN |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 491 Регистрация: 8.8.2006 Репутация: 3 Всего: 18 |
Почему. лучше. ? |
|||
|
||||
MetalFan |
|
|||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 62 Всего: 128 |
смотря что подразумевается под "делать все самому"... если имеется ввиду неиспользование CopyFrom, то здесь я тоже не согласен. ХОТЯ есть некоторые моменты, когда CopyFrom не подходит... -------------------- There are always someone smarter than you... |
|||
|
||||
kami |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 23 Всего: 72 |
![]() CopyFrom передвинет сам указатель на нужное количество байт. В этом случае манипуляции с Seek (или оберткой над ним - Position) - потенциальный глюкодром, причем достаточно неявный. Можно пример "навскидку"? Просто я всегда, когда нужно перекинуть данные из одного TStream в другой, пользуюсь CopyFrom (а его второй параметр :=0 - это вообще песня ![]() |
|||
|
||||
AntonN |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 491 Регистрация: 8.8.2006 Репутация: 3 Всего: 18 |
Вот когда ты вручную указываешь позицию куда писать - ты можешь точно видеть в коде откуда он пишет. А когда надеешься на невидимый указатель который "вроде бы должен быть тут" - вот это уже потенциальный глюкодром ![]() MetalFan,
подразумевается "выполнять position:=" когда точно нужно быть увереным в какую позицию должен установиться указатель. Добавлено через 7 минут и 5 секунд дополню на всякий случай, что опыта на стримах съел прилично, старый кусочек его вывалился в первых постах (который за час обрастает нужными полями в хедере (название файла, атрибуты и тп), прикручивается zlib и если надо шифрование). Никакого глюкодрома за годА плотного щупанья TFileStream.position я не встречал, зато часто натыкался на свои же грабли когда указатель после Write был не там, где должен быть перед очередной операцией (в основном связано было с модификацией кода, когда подзабывалась структура файла). |
||||
|
|||||
kami |
|
||||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 23 Всего: 72 |
В контексте данной задачи это (на мой взгляд) будет выглядеть примерно так: 1. установить указатель в 0. Loop: 2. считать длину файла (и при необходимости - имя, атрибуты и т.д.) 3. запомнить позицию указателя 4. считать файл из потока 5. установить указатель на "запомненный"+длина файла goto Loop (пока не достигнем конца потока). Если доводить до абсурда - то каждая четная операция(2,4) тоже должна обрамляться запоминанием предыдущего положения указателя и ручным передвиганием его дальше. Извините, но... "это не наш метод". Большинство из посетителей форума могут сказать то же самое. ... не будем начинать холивар, тем более что к теме он относится слабо ![]() Добавлено через 1 минуту и 36 секунд
А именно поэтому Read и Write методы TStream - это функции. Возвращающие реальное количество считанного/записанного. |
||||
|
|||||
MetalFan |
|
||||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 62 Всего: 128 |
ребят, ну не устраивайте тут считалки. Ctrl+Click еще никто не отменял. а код CopyFrom не так уж и сложен для понимания. и сразу отпадут все вопросы, при каких входных данных этот злобный CopyFrom какие выходные данные оставит) если кому что-то непонятно, могу здесь код CopyFrom прокомментировать. да на здоровье) единственной проблемой, с которой я столкнулся при использовании метода TStream.CopyFrom, и из-за которой от него пришлось отказаться, это была проблема, связанная с использованием ZLib.TCompressStream, ZLib.TDecompressStream... в частности при распаковке потока следующим кодом:
ибо TDecompressionStream не умеет делать Seek(0, soFromEnd)... т.е. мы не узнаем размер распакованных данных, не распаковав их, или не сохранив из предварительно в том же потоке(к примеру). тогда вместо CopyFrom пришлось использовать нечто такое:
ну вот как-то так... -------------------- There are always someone smarter than you... |
||||
|
|||||
kami |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 23 Всего: 72 |
||||
|
||||
MetalFan |
|
|||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 62 Всего: 128 |
а какие еще были причины? хотя это наверное уже злостный оффтоп будет) -------------------- There are always someone smarter than you... |
|||
|
||||
Yanis |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2937 Регистрация: 9.2.2004 Где: Москва Репутация: 72 Всего: 111 |
||||
|
||||
![]() ![]() ![]() |
Правила форума "Delphi: Общие вопросы" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |