1С 8.3 Чтение GZip - Программист 1С Минск. Автоматизация бизнеса.

Перейти к контенту

1С 8.3 Чтение GZip

Перейти в основной раздел:
Структурированная copypaste с github.com для работа с GZip (форматом и утилитой сжатия и восстановления/декомпрессии файлов, использующая алгоритм Deflate).
Библиотека работы с утилитой GZip в 1С 8.3 (Основная функция):
Функция ПрочитатьGZip(СжатыеДанные) Экспорт

   РазмерПрефиксаGZip = 10;
   РазмерПостфиксаGZip = 8;

   Данные = Новый ЧтениеДанных(СжатыеДанные);
   Данные.Пропустить(РазмерПрефиксаGZip);
   РазмерСжатыхДанных = Данные.ИсходныйПоток().Размер() - РазмерПрефиксаGZip - РазмерПостфиксаGZip;

   ПотокZip = Новый ПотокВПамяти(ZipРазмерLFH() + РазмерСжатыхДанных + ZipРазмерDD() + ZipРазмерCDH() + ZipРазмерEOCD());
   ЗаписьДанных = Новый ЗаписьДанных(ПотокZip);
   ЗаписьДанных.ЗаписатьБуферДвоичныхДанных(ZipLFH());
   Данные.КопироватьВ(ЗаписьДанных, РазмерСжатыхДанных);

   ЗаписьДанных.Закрыть();
   ЗаписьДанных = Новый ЗаписьДанных(ПотокZip);

   CRC32 = Данные.ПрочитатьЦелое32();
   РазмерНесжатыхДанных = Данные.ПрочитатьЦелое32();
   Данные.Закрыть();

   ЗаписьДанных.ЗаписатьБуферДвоичныхДанных(ZipDD(CRC32, РазмерСжатыхДанных, РазмерНесжатыхДанных));
   ЗаписьДанных.ЗаписатьБуферДвоичныхДанных(ZipCDH(CRC32, РазмерСжатыхДанных, РазмерНесжатыхДанных));
   ЗаписьДанных.ЗаписатьБуферДвоичныхДанных(ZipEOCD(РазмерСжатыхДанных));
   ЗаписьДанных.Закрыть();

   Возврат ПрочитатьZip(ПотокZip);

КонецФункции
Библиотека работы с утилитой GZip в 1С 8.3 (Вспомогательные функции):
Функция ПрочитатьZip(СжатыеДанные, ТекстОшибки = Неопределено)

    #Если МобильноеПриложениеСервер Тогда
       ВызватьИсключение(НСтр("ru = 'Работа с Zip-файлами в мобильной платформе не поддерживается'"));
    #Иначе
       Каталог = ПолучитьИмяВременногоФайла();
       ЧтениеZip = Новый ЧтениеZipФайла(СжатыеДанные);
       ИмяФайла = ЧтениеZip.Элементы[0].Имя;
       Попытка
           ЧтениеZip.Извлечь(ЧтениеZip.Элементы[0], Каталог, РежимВосстановленияПутейФайловZIP.НеВосстанавливать);
       Исключение
           // Игнорируем проверку целостности архива, просто читаем результат
           ТекстОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
       КонецПопытки;
       ЧтениеZip.Закрыть();

       Результат = Новый ДвоичныеДанные(Каталог + ПолучитьРазделительПути() + ИмяФайла);
       УдалитьФайлы(Каталог);

       Возврат Результат;
    #КонецЕсли

КонецФункции

#Область СлужебныеСтруктурыZip
// Описание структур см. здесь https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT

Функция ZipРазмерLFH()

   Возврат 34;

КонецФункции

Функция ZipРазмерDD()

   Возврат 16;

КонецФункции

Функция ZipРазмерCDH()

   Возврат 50;

КонецФункции

Функция ZipРазмерEOCD()

   Возврат 22;

КонецФункции

Функция ZipLFH()

   // Local file header
   Буфер = Новый БуферДвоичныхДанных(ZipРазмерLFH());
   Буфер.ЗаписатьЦелое32(0, 67324752); // signature 0x04034b50
   Буфер.ЗаписатьЦелое16(4, 20);       // version
   Буфер.ЗаписатьЦелое16(6, 10);       // bit flags
   Буфер.ЗаписатьЦелое16(8, 8);        // compression method
   Буфер.ЗаписатьЦелое16(10, 0);       // time
   Буфер.ЗаписатьЦелое16(12, 0);       // date
   Буфер.ЗаписатьЦелое32(14, 0);       // crc-32
   Буфер.ЗаписатьЦелое32(18, 0);       // compressed size
   Буфер.ЗаписатьЦелое32(22, 0);       // uncompressed size
   Буфер.ЗаписатьЦелое16(26, 4);       // filename legth - "data"
   Буфер.ЗаписатьЦелое16(28, 0);       // extra field length
   Буфер.Записать(30, ПолучитьБуферДвоичныхДанныхИзСтроки("data", "ascii", Ложь));

   Возврат Буфер;

КонецФункции

Функция ZipDD(CRC32, РазмерСжатыхДанных, РазмерНесжатыхДанных)

   // Data descriptor
   Буфер = Новый БуферДвоичныхДанных(ZipРазмерDD());
   Буфер.ЗаписатьЦелое32(0, 134695760);
   Буфер.ЗаписатьЦелое32(4, CRC32);
   Буфер.ЗаписатьЦелое32(8, РазмерСжатыхДанных);
   Буфер.ЗаписатьЦелое32(12, РазмерНесжатыхДанных);

   Возврат Буфер;

КонецФункции

Функция ZipCDH(CRC32, РазмерСжатыхДанных, РазмерНесжатыхДанных)

   // Central directory header
   Буфер = Новый БуферДвоичныхДанных(ZipРазмерCDH());
   Буфер.ЗаписатьЦелое32(0, 33639248);              // signature 0x02014b50
   Буфер.ЗаписатьЦелое16(4, 798);                   // version made by
   Буфер.ЗаписатьЦелое16(6, 20);                    // version needed to extract
   Буфер.ЗаписатьЦелое16(8, 10);                    // bit flags
   Буфер.ЗаписатьЦелое16(10, 8);                    // compression method
   Буфер.ЗаписатьЦелое16(12, 0);                    // time
   Буфер.ЗаписатьЦелое16(14, 0);                    // date
   Буфер.ЗаписатьЦелое32(16, CRC32);                // crc-32
   Буфер.ЗаписатьЦелое32(20, РазмерСжатыхДанных);   // compressed size
   Буфер.ЗаписатьЦелое32(24, РазмерНесжатыхДанных); // uncompressed size
   Буфер.ЗаписатьЦелое16(28, 4);                    // file name length
   Буфер.ЗаписатьЦелое16(30, 0);                    // extra field length
   Буфер.ЗаписатьЦелое16(32, 0);                    // file comment length
   Буфер.ЗаписатьЦелое16(34, 0);                    // disk number start
   Буфер.ЗаписатьЦелое16(36, 0);                    // internal file attributes
   Буфер.ЗаписатьЦелое32(38, 2176057344);           // external file attributes
   Буфер.ЗаписатьЦелое32(42, 0);                    // relative offset of local header
   Буфер.Записать(46, ПолучитьБуферДвоичныхДанныхИзСтроки("data", "ascii", Ложь));

   Возврат Буфер;

КонецФункции

Функция ZipEOCD(РазмерСжатыхДанных)

   // End of central directory
   РазмерCDH = 50;
   Буфер = Новый БуферДвоичныхДанных(ZipРазмерEOCD());
   Буфер.ЗаписатьЦелое32(0, 101010256); // signature 0x06054b50
   Буфер.ЗаписатьЦелое16(4, 0); // number of this disk
   Буфер.ЗаписатьЦелое16(6, 0); // number of the disk with the start of the central directory
   Буфер.ЗаписатьЦелое16(8, 1); // total number of entries in the central directory on this disk
   Буфер.ЗаписатьЦелое16(10, 1); // total number of entries in the central directory
   Буфер.ЗаписатьЦелое32(12, РазмерCDH); // size of the central directory
   // offset of start of central directory with respect to the starting disk number
   Буфер.ЗаписатьЦелое32(16, ZipРазмерLFH() + РазмерСжатыхДанных + ZipРазмерDD());
   Буфер.ЗаписатьЦелое16(20, 0); // the starting disk number

   Возврат Буфер;

КонецФункции

#КонецОбласти

#Область СлужебныеСтруктурыGZip

// Описание структур см. здесь https://www.ietf.org/rfc/rfc1952.txt

Функция GZipРазмерHeader()

   Возврат 10;

КонецФункции

Функция GZipРазмерFooter()

   Возврат 8;

КонецФункции

Функция GZipHeader()

   Буфер = Новый БуферДвоичныхДанных(GZipРазмерHeader());
   Буфер[0] = 31;               // ID1 0x1f
   Буфер[1] = 139;              // ID2 0x8b
   Буфер[2] = 8;                // compression method (08 for DEFLATE)
   Буфер[3] = 0;                // header flags
   Буфер.ЗаписатьЦелое32(4, 0); // timestamp
   Буфер[8] = 0;                // compression flags
   Буфер[9] = 255;              // operating system ID

   Возврат Буфер;

КонецФункции

Функция GZipFooter(CRC32, РазмерИсходныхДанных)

   Буфер = Новый БуферДвоичныхДанных(GZipРазмерFooter());
   Буфер.ЗаписатьЦелое32(0, CRC32);
   Буфер.ЗаписатьЦелое32(4, РазмерИсходныхДанных);

   Возврат Буфер;

КонецФункции

#КонецОбласти
От подписчика:
Чтение GZip через ХранилищеЗначения в 1С 8.3 (без внешних компонент):
#Область СлужебныеСтруктурыZip

&НаСервереБезКонтекста
Функция ЧтениеGZipЧерезХранилищеЗначения(ТелоКакДвоичныеДанные, СтрокаHexВФорматеBase16) Экспорт

   // Размер gzip compressed blocks (ожидаем структуру gzip = 10байт заголовок + дефлейт + 8байт подвал):
   РазмерGZip = ТелоКакДвоичныеДанные.Размер() - 18;

   //104 = 18 определение +5 block no compression + 69 определение ХЗ +  12 4пуст/4размер/4пуст:
   Буфер = Новый БуферДвоичныхДанных(РазмерGZip + 104);
   Буфер.Записать(0, ПолучитьБуферДвоичныхДанныхИзHexСтроки(СтрокаHexВФорматеBase16),92);

   ПотокGZip = ТелоКакДвоичныеДанные.ОткрытьПотокДляЧтения();
   ПотокGZip.Перейти(10, ПозицияВПотоке.Начало);// позиционируем на начало дефлейта
   ПотокGZip.Прочитать(Буфер, 104, РазмерGZip);
   ПотокGZip.Перейти(4, ПозицияВПотоке.Текущая);// позиционируем на байты размера несжатых данных данных
   ПотокGZip.Прочитать(Буфер, 96, 4);

   Возврат XMLЗначение(Тип("ХранилищеЗначения"), Base64Строка(ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(Буфер))).Получить();

КонецФункции

#КонецОбласти
3
комментарии
Админ -> Денису
07 ноя 2024
Можете прислать пример через форму: https://koder.by/add_1c_code.php ?
Для публикации на этой странице.
07 ноя 2024
Какой длинный код. Пользовался подобным, пока не обнаружил, что через ХранилищеЗначений можно распаковать gzip девятью строками кода.
Александр
17 авг 2024
Здравствуйте!

Подсмотрел Ваш код. Вставил его в свой модуль, всё отрабатывает штатно. Только я в силу отсутствия достаточных знаний в области так называемого модификации файла на уровне потока не могу сообразить, как пользоваться с получаемыми двоичными данными. Я их записываю в ZIP-файл, подразумевая, что это уже форматированные под ZIP двоичные данные. Но в итоге при чтении файла выдаётся ошибка. Как всё-таки надо поступать с полученными данными из функции ПолучитьZip()? В какой формат файла эту информацию дальше следует записывать?

Благодарю!
____________________
Copyright©, «Программист 1С в г.Минске», 21.12.2023
Перепечатка текста и фотографий разрешена при наличии прямой ссылки на источник
Яндекс.Метрика
Защищенное соединение ssl
visa
mastercard
Maestro
Яндекс деньги
Назад к содержимому