IE2017

[x1c.ru] DefInf: Упаковка/распаковка файлов по алгоритму Deflate средствами 1С без ВК и сторонних приложений (Deflate/Inflate)

Программирование - Инструментарий

Собственно говоря, это набор функций, которые пакуют по алгоритму Deflate и распаковывают файлы, плюс функции для помещения двоичного файла в массив и обратно.

Благодарности

Как обычно, сначала благодарности:

brix8x за публикацию V8Unpack 2.0

//infostart.ru/public/15695/

Эта программа очень помогла в тестировании функций по упаковке/распаковке файлов.

Для чего можно использовать

Deflate часто используется для уменьшения размера файлов, используется при сжатии графических, звуковых файлов и т.д., так что пригодиться может в различных областях. В 1С Deflate используется для сжатия метаданных.

Как это работает

Всю работу по упаковке/распаковке делают 1С-объекты ЧтениеZIPФайла и ЗаписьZIPФайла, функции обработки только используют результаты их работы.

Deflate

Создается ZIP-файл объектов ЗаписьZIPФайла, содержащий 1 пакуемый файл, а затем из этого ZIP-файла извлекаются байты, которые представляют собой наш файл, сжатый по алгоритму Deflate.

Inflate

Создается ZIP-файл объектом ЗаписьZIPФайла, в который помещается упакованный файл, только путем копирования, а не сжатия, затем в ZIP-файле меняется заголовок с указанием того, что файл сжатый, длина распакованного файла ставится равной 1, затем файл извлекается объектом ЧтениеZipФайла, который и распаковывает файл. Из-за того, что CRC ZIP-файла некорректный и длина распакованного файла указывается неверно (равна 1), платформа 1С вызывает исключение, но при этом файл распаковывается.

Работа с байтами

 Поскольку для этих функций нужен бинарный доступ к файлам, он осуществляется так:

Файл->Объект ДвоичныеДанные->Строка Base64->Массив->Все необходимые действия в массиве->Строка Base64->Двоичные данные->Файл

И вот тут начинаются

Недостатки

Из-за преобразования строки base64 в массив байтов и обратно скорость работы невысока. На Win8 32bit Intel 2x2,3 Hz файл в 1 Мб загружается в массив примерно 30 секунд (и столько же примерно выгружается). В принципе, для тех задач, под которые создавались эти функции, это оказалось вполне приемлемо.

Файлы, размер которых при сжатии объектом ЗаписьZIPФайла не уменьшается (очень маленькие файлы или уже упакованные, например, архивы rar, zip), не пакуются Deflate-ом, а копируются в ZIP-файл, и таким образом по Deflate не пакуются. Тут возможны различные решения, например, если не пакуется маленький текстовый файл, то добавить в него строку (например, комментарий в программный код), которая при упаковке точно уменьшит его размер, а при распаковке эту строку убирать. С бинарным файлом можно поступать аналогично, но пока следить за этим должен тот, кто пользуется функциями библиотеки.

Работоспособность

Обработка тестировалась на Windows 8 (32bit) и на релизе платформы 8.3.5.1383.

История версий

0.0.1.3a от 28.01.2015 Первая публичная версия (альфа)


Скачать файлы

Наименование Файл Версия Размер
x1c_DefInf_20150128_0_0_1_3a.epf
.epf 13,84Kb
28.01.15
31
.epf 0.0.1.3a 13,84Kb 31 Скачать

См. также

Комментарии
1. Pavel Fomin (Pasha1st) 503 28.01.15 23:31 Сейчас в теме
Могу дать бесплатный совет.
Base64 кодирует данные по 3 байта в 4 символа. Следовательно, если смещение нужного нам блока кратно 3 можно просто выбрать подстроку с известной (расчетной) позиции, и подкорректировать "хвостик" - последнюю четверку символов.
А управлять смещением данных можно изменяя длину имени сжатого файла.
2. eugenie zheludkov (eugeniezheludkov) 32 29.01.15 02:06 Сейчас в теме
кстати можно реализовать без создания файлов на диске
 
-упаковка
Упакован = СтрЗаменить(СтрЗаменить(ЗначениеВСтрокувнутр(Новый ХранилищеЗначения(ИсходныйТекст, new СжатиеДанных(9))),Символы.ПС,Символы.ПС+"|"),"""","""""");
   ........................................................
-распаковка обратно
ИсходныйТекст=Вычислить("ЗначениеИзСтрокиВнутр("""+Упакован+""").Получить()");
  
...Показать Скрыть

насчет быстрой обработки двоичных данных можно взглянуть в сторону com объекта "adodb.stream" есть много примеров как быстро обрабатывать большие массивы данных с его помощью
3. Николай Гусев (GusevNA) 274 29.01.15 16:38 Сейчас в теме
(2) eugeniezheludkov, Была такая мысль, но, во-первых, ЗначениеВСтрокуВнутр, хоть и нормально работает, но "Используется для сохранения функциональной совместимости с 1С:Предприятием 7.7. Использовать для других целей не рекомендуется", а во-вторых, доступно только "Сервер, толстый клиент, внешнее соединение"

ADODB.Stream удобный, но иногда его не любят из-за дырок в безопасности, я обычно использую SAPI.spFileStream, но в любом случае и то, и другое - это внешние для среды "1С Предприятие" компоненты, а задача изначально стояла написать все на 1С Хотя, чтобы организовать бинарное чтение/запись через ActiveX, там нужно переписать всего пару функций
4. Николай Гусев (GusevNA) 274 29.01.15 16:40 Сейчас в теме
(1) Pasha1st, Спасибо насчет смещения длиной имени файла - сразу не догадался. Если для реальной работы нужна будет оптимизация скорости, обязательно воспользуюсь.
5. Дмитрий Семенов (Sam13) 215 18.05.16 12:05 Сейчас в теме
Коллекги, плиз, хелп!
Стоит задача подготовить препроводительную ведомость для сбербанка, данные которой должны быть закодированы также в двумерном штрихкоде.
Штрихкод формируется следующим образом:
- формируется XML-описание препроводительной ведомости
- к результирующему XML применяется deflate
- затем результат кодируется base64, к результирующей строке добавляется сигнатура @NN@ - номер версии формата. 01 или 02
c deflate и base64 возникли проблемы.

В инструкции сбербанка приведена закодированная строка (сжатая) и ее xml-исходник и команда проверки (linuxового шелла)
echo "@01@eJw9UMlugzAQvfcrkO/ENoZCpWFy6xe0Z+SAS1CMHWGKmr/vmM2nt4z­fLHD9G22ymCkM3tVMXgRLjGt9N7i+Zt9fn2nFkjBr12nrnamZ8+yK8GwW0yF­0etaYCalSkadZBnwVwDX+huVHkQtZlVIKehL4qpIXXuNDo8qLTOVR3ThMTXs­3M+aiFFklRaEqWdBHVah34LsJYWoxTH330wfgkYDz4+C0bR7engSp5UUICt8­5RJdGWIsWbWk/g9QE+EGiOr+eBuOkBz4DtnQa9OZtOAAKWniHEH7Hs2vEh0P­VfDvW2z8i03VO" | sed 's/@01@//' | base64 -d | zlib-flate -uncompress

Результат:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><p_ved><data>2013-04-22</data><n_ob>795401871100001</n_ob><n_symka>345234</n_symk­a><r_chet>40702810538150003536</r_chet><src>srgdfgs</src><no­minal_kol><nominal>100.00</nominal><kol>1</kol><valcode>810</valcode><valtype>01</v­altype></nominal_kol><symbols><symbol>02</symbol><sum>100.00</sum></symbols></p_ved>

Как я не бился, у меня не удается получить сходный результат

Как получить результат, который был сходным со сбербанком? Имею ввиду именно кодирование deflate
6. mbzapas 13.01.17 21:03 Сейчас в теме
Хорошая идея, но в 8.3.9 кажется уже не работает :(
7. Сергей Толмачев (sss999) 35 14.03.17 21:11 Сейчас в теме
я смогу файл dt распаковать?
8. Николай Гусев (GusevNA) 274 15.03.17 09:32 Сейчас в теме
(7)dt не распакует, у него другой формат файла
Оставьте свое сообщение