gifts2017

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

Опубликовал Николай Гусев (GusevNA) в раздел Программирование - Инструментарий

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

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

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

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

http://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
27
.epf 0.0.1.3a 13,84Kb 27 Скачать

См. также

PowerTools от 1 000
Подписаться Добавить вознаграждение

Комментарии

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

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

ADODB.Stream удобный, но иногда его не любят из-за дырок в безопасности, я обычно использую SAPI.spFileStream, но в любом случае и то, и другое - это внешние для среды "1С Предприятие" компоненты, а задача изначально стояла написать все на 1С Хотя, чтобы организовать бинарное чтение/запись через ActiveX, там нужно переписать всего пару функций
4. Николай Гусев (GusevNA) 29.01.15 16:40
(1) Pasha1st, Спасибо насчет смещения длиной имени файла - сразу не догадался. Если для реальной работы нужна будет оптимизация скорости, обязательно воспользуюсь.
5. Дмитрий Семенов (Sam13) 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
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа