Blog. Just Blog

Упаковка и распаковка данных с помощью библиотеки zlib

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Упаковка и распаковка данных с помощью библиотеки zlib
Упаковка и распаковка данных с помощью библиотеки zlib

Продолжаем тему упаковки и распаковки. Сегодня в качестве инструмента будет известная библиотека zlib от Jean-loup Gailly и Mark Adler, признанных профессионалов в области компрессии данных. Ну а что, по системным функциям прошлись, почему бы не пройтись по сторонним библиотекам. Тем более, что zlib используется во многих программных продуктах, и, если вдруг возникнет необходимость поковыряться в их базах, то будет уже практически готовое решение.

Скомпилированных библиотек zlib последней версии для Windows почему-то не нашлось ни на офсайте, ни в репозитории, так что пришлось заниматься сборкой исходников самостоятельно. Хорошо хоть, что авторы приложили проект для студии, уже проще. Готовую zlibwapi.dll можно взять в архиве из этой статьи.

По степени компрессии на небольших объемах данных zlib заметно уступает лидерам типа aPLib или BitBuster. На больших объемах ситуация выравнивается, разница в сжатии практически незаметна, но при этом сохраняется просто космическая скорость обработки данных в обе стороны.

Переходим к программированию. Для доступа к компрессии и декомпрессии достаточно добавить zlibwapi.dll в дистрибутив с вашим приложением и прописать в таблице импорта нужные функции. В документации сказано об основных функциях (де)компресии, а также о работе со сжатыми файлами. Разберем на примерах оба варианта, начнем с работы с данными в памяти.
  1.         ; Определить максимальный размер памяти
  2.         ; для размещения упакованных данных
  3.         mov     [original_size],???    ; размер оригинальных данных
  4.         invoke  compressBound,[original_size]
  5.         mov     [compressed_size],eax
  6.  
  7.         ; Зарезервировать память
  8.         invoke  GlobalAlloc,GMEM_MOVEABLE,[compressed_size]
  9.         mov     [hMem],eax
  10.         invoke  GlobalLock,eax
  11.         mov     [dMem],eax
  12.  
  13.         ; Сжать данные с максимальной компрессией
  14.         Z_BEST_COMPRESSION = 9
  15.         invoke  compress2,[dMem],compressed_size,original_data,\
  16.                 [original_size],Z_BEST_COMPRESSION
Так как объем упакованных данных заранее неизвестен, с помощью функции compressBound можно получить минимально необходимый размер блока памяти, в который гарантированно поместятся данные после упаковки. Дальше выделяем память стандартными функциями и вызываем функцию zlib compress2. От функции compress она отличается только возможностью выбрать степень сжатия. Обратите внимание, что при упаковке размер исходных данных нигде не сохраняется, об этом вы должны позаботиться самостоятельно. Фактический размер упакованных данных будет записан в переменную compressed_size, а ее начальное значение будет потеряно.
  1.         ; Зарезервировать память
  2.         mov     [original_size],???    ; размер оригинальных данных
  3.         invoke  GlobalAlloc,GMEM_MOVEABLE,[original_size]
  4.         mov     [hMem],eax
  5.         invoke  GlobalLock,eax
  6.         mov     [dMem],eax
  7.  
  8.         ; Распаковать данные
  9.         mov     [compressed_size],???  ; размер упакованных данных
  10.         invoke  uncompress,[dMem],original_size,\
  11.                 compressed_data,[compressed_size]
  1.         ; Зарезервировать память
  2.         mov     [original_size],???    ; размер оригинальных данных
  3.         invoke  GlobalAlloc,GMEM_MOVEABLE,[original_size]
  4.         mov     [hMem],eax
  5.         invoke  GlobalLock,eax
  6.         mov     [dMem],eax
  7.  
  8.         ; Распаковать данные
  9.         mov     [compressed_size],???  ; размер упакованных данных
  10.         invoke  uncompress2,[dMem],original_size,\
  11.                 compressed_data,compressed_size
Для распаковки используется обратная функция uncompress или uncompress2. Как я уже говорил, размер оригинальных данных для резервирования памяти под них вы должны определять самостоятельно. После распаковки с помощью uncompress2 фактический размер извлеченных данных записывается в переменную original_size, а размер обработанных упакованных данных - в переменную compressed_size. Если размер обработанных упакованных данных вас не интересует, то достаточно функции uncompress.

Очень большое преимущество библиотеки zlib - работа напрямую с файлами, если упакованные данные должны храниться там целиком. Вам не надо самостоятельно резервировать память для загрузки содержимого файла, не надо заботиться о чтении или записи данных, всю грязную работу библиотека возьмет на себя. Функций для работы с файлами много, но для большинства ситуаций хватит четырех: gzopen, gzread / gzwrite и gzclose.
  1. fname   db 'packed.gz',0
  2. fmode   db 'rb',0
  3.         ...
  4.         ...
  5.         ; Открыть файл с упакованными данными
  6.         invoke  gzopen,fname,fmode
  7.         mov     ebx,eax
  8.         ; Прочитать и распаковать данные
  9.         invoke  gzread,ebx,original_data,[original_size]
  10.         ; Закрыть файл
  11.         invoke  gzclose,ebx
В этом примере содержимое файла будет целиком прочитано и распаковано в указанный блок памяти. Еще раз напомню, что о хранении размера оригинальных данных вы должны позаботиться заранее.
  1. fname   db 'packed.gz',0
  2. fmode   db 'wb',0
  3.         ...
  4.         ...
  5.         ; Создать файл-приемник упакованных данных
  6.         invoke  gzopen,fname,fmode
  7.         mov     ebx,eax
  8.         ; Записать упакованные данные
  9.         invoke  gzwrite,ebx,original_data,[original_size]
  10.         ; Закрыть файл
  11.         invoke  gzclose,ebx
Тут данные из памяти упаковываются и сохраняются в указанный файл. Другие функции zlib для работы с файлами смотрите в документации.

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

В приложении примеры программ с исходными текстами, одна из которых извлекает из памяти иконку, упакованную по алгоритму compress библиотеки zlib, и выводит ее на форму. Вторая программа загружает иконку из файла, упакованного по алгоритму gzip. Также в архиве примеры простеньких упаковщиков на основе zlib, работающих из командной строки.

Примеры программ с исходными текстами (FASM)Примеры программ с исходными текстами (FASM)

ZLIB.Pack.Unpack.Demo.zip (64,439 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 2160 | Комментариев: 4

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (13.12.2021 в 20:11):
Слова "ПОСЛЕДНЕЙ ВЕРСИИ" не считаются? По этим ссылкам выложены какие-то допотопные версии, одна другой древнее.
Petya (13.12.2021 в 20:07):
ЦитатаСкомпилированных библиотек zlib последней версии для Windows почему-то не нашлось

Пара ссылок внизу главной офсайта не считаются?
Цитата*  zlib for Windows 9x/NT/2000/XP/2003 (DLL version, plus related utilities)
*  zlib for Windows 9x/NT (DLL and static version)
ManHunter (10.12.2021 в 15:44):
Не хлебом единым. В первую очередь я кодер, а кушать уже потом.
Гость (10.12.2021 в 15:42):
надо побольше кулинарных рецептов, хороших и разных!

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2025
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0082 сек.) / Память: 4.5 Mb
Наверх