1С 8.3 Чтение GZip
Данные > Примеры кода 1С > 1С 8.3 ZIP
Перейти в основной раздел:
Структурированная 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 = 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, РазмерИсходныхДанных);
Возврат Буфер;
КонецФункции
#КонецОбласти
#Если МобильноеПриложениеСервер Тогда
ВызватьИсключение(НСтр("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Строка(ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(Буфер))).Получить();
КонецФункции
Функция Чтение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()? В какой формат файла эту информацию дальше следует записывать?
Благодарю!
Подсмотрел Ваш код. Вставил его в свой модуль, всё отрабатывает штатно. Только я в силу отсутствия достаточных знаний в области так называемого модификации файла на уровне потока не могу сообразить, как пользоваться с получаемыми двоичными данными. Я их записываю в ZIP-файл, подразумевая, что это уже форматированные под ZIP двоичные данные. Но в итоге при чтении файла выдаётся ошибка. Как всё-таки надо поступать с полученными данными из функции ПолучитьZip()? В какой формат файла эту информацию дальше следует записывать?
Благодарю!
____________________
Перепечатка текста и фотографий разрешена при наличии прямой ссылки на источник