Альтернативное получение значения из хранилища значения. Свой ХранилищеЗначения.Получить();

22.04.19

Интеграция - Файловый обмен (TXT, XML, DBF), FTP

Данная публикация не претендует на использование в продакшене, но когда "Нельзя, но очень хочется" в отношении получения ооочень больших данных из ХранилищаЗначения и когда сама платформа не может получить значение и падает, при этом, перед падением съедает почти всю память. Это своего рода костыль, в безвыходной ситуации. Речь пойдет про получение больших данных из хранилища значения в файловых базах на 32-х битной платформе. Данное не касается 64-х битных клиентов/серверов где нет ограничения на размер потребляемой памяти (верней есть, но доступно памяти гораздо больше, чем 32-х битному приложению без PAE).

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

Наименование Файл Версия Размер
Альтернативное получение значения из хранилища значения. Свой ХранилищеЗначения.Получить();:
.epf 12,71Kb
14
.epf 0.1 12,71Kb 14 Скачать

Однажды, когда я был молодой и глупый (последнее правда с тех под и не изменилось), я решал задачу автоматического РИБ обмена через веб-сервис и в качестве контейнера для данных, я решил использовать передачу хранилища значения, в котором упакована с сжатием (9) строка содержимым XML файла сообщения. И всё бы ничего, работало это без проблем. Как вдруг, попался один узел, для которого накопилось ну очень много данных (смотря конечно для кого), а именно, XML данные весили чуть больше 400 Мб. в сжатом виде же это занимало примерно 60 Мб, через интернет клиент веб-сервиса данные то скачал, но при попытке ХранилищеЗначение.Получить(); (База файловая, памяти 2 Гб) 1С сначала кушала память ложками, до без малого 1 Гб съедала и с грохотом падала пугая голубей в соседнем дворе. Конечно, ручной обмен ни-кто не отменял (через классические файлы) и там всё проходило без проблем (как минимум по тому, что 1С не весь файл XML читает в память). Данная проблема воспроизводилась как на релизах 8.3.10.2699 и 8.3.12.1855 так и на других версиях.

А вы знали? 1С любит держать данные помещенные в ХранилищеЗначения в временном файле на диске? Разумеется имеется ввиду те данные, то лежат в памяти. Возможно, она так любит избавляться только от больших данных, но это уже совсем другая история...

Я было просто забил на проблему, ибо она редкая и можно обмен сделать ручками, так как просто не представлял как её можно решить, но тут я совершенно случайно наткнулся отличную публикацию: //infostart.ru/public/618906/ от SerVer1C (за что ему огромное спасибо!) и тут понеслось... Итогом этого, стал собственный метод, получающий значение хранилища значений, который по минимуму питается оперативной памятью, предпочитая ей обычный диск и главное, не валящий процесс 1С ну и конечно выполняющий свою задачу ;)

Суть решения "проста", запакованное хранилище значения из себя представляет данные, запакованные алгоритмом Deflate (которая сама 1С использует везде, а доступа к методам дать не могут) и некоторое служебные данные. Этим же методом Deflate, упаковываются ZIP архивы. Итого весь процесс проводится к следующему:

1) Получение из хранилища значений двоичных данных (да-да, 1С не добавила возможности прямого получения):

ДанныеВBase64 = XMLСтрока(ХранилищеЗначения); // Получим Base64 хранилища значения
ДвоичныеДанные = Base64Значение(ДанныеВBase64); // Получаем двоичные данные хранилища значения

2) Получаем буфер двоичных за вычетом префикса хранилища значения

РазмерСлужебногоЗаголовка = 18; // Размер в байтах служебного заголовка хранилища значения
Поток = ДвоичныеДанные.ОткрытьПотокДляЧтения(); // Открываем поток для данных
Поток.Перейти(РазмерСлужебногоЗаголовка, ПозицияВПотоке.Начало); // Прыгаем в начало данных
РазмерПотока = Поток.Размер() - РазмерСлужебногоЗаголовка;
БуферТелаФайла = Новый БуферДвоичныхДанных(РазмерПотока); // Создаем буфер под данные
Поток.Прочитать(БуферТелаФайла, 0, РазмерПотока); // Читаем данные в буфер
Поток.Закрыть();

3) Формируем структуру ZIP архива и добавляем к нему данные из буфера двоичных данных

ДлинаИмениСжатогоФайла		= СтрДлина(ИмяФайлаВАрхиве);
РазмерСжатогоФайла			= РазмерПотока;
... // Подробнее можно ознакомится в приложенном файле и/или в исходной публикации: //infostart.ru/public/618906/
НовыйБинарник = ПотокВПамяти.ЗакрытьИПолучитьДвоичныеДанные();
НовыйБинарник.Записать(ПутьКФайлуАрхива);
ПотокВПамяти.Закрыть();

4) Распаковать ZIP архив, игнорируя ошибки распаковки (так как у нас нет данных о CRC сумме НЕ запакованных данных, а так же об их размере)

// Можно было и в памяти извлекать, но слишком много памяти кушает
Архив = Новый ЧтениеZipФайла(ПутьКФайлуАрхива);
Попытка
	Архив.Извлечь(Архив.Элементы[0], КаталогОбмена);
	//файл извлечется, хотя здесь возникнет исключение из-за некорректных размера файла и контрольной суммы
Исключение
КонецПопытки;

5) На выходе, мы уже получаем распакованные данные, которые были помещены в хранилище значения, НО, они окружены структурой, похожей на JSON которая всюду используется в 1С как минимум с 1С 7.7 (или даже раньше), для того чтобы от неё избавится, надо в начале файла отрезать чуток и в конце, а так-же убрать экранирование кавычек. Тут я пробовал разные варианты (кроме считывания всего текста и СтрЗаменить, ибо память не безлимитная, но и такой способ работает и 1С не падает), но самым оптимальным как по скорости, так и по потреблению памяти, оказалось порционное чтение из файла, замена двойных кавычек на одинарные и запись в результирующий файл (выполняется мгновенно, пруфов нет)

ПотокЧтения = Новый ФайловыйПоток(ПутьКИзвлеченномуФайлу, РежимОткрытияФайла.Открыть, ДоступКФайлу.Чтение);
ЧтениеТекста = Новый ЧтениеТекста(ПотокЧтения, КодировкаТекста.UTF8);
ПотокЗаписи = Новый ФайловыйПоток(ПутьКФайлуРезультата, РежимОткрытияФайла.Создать, ДоступКФайлу.Запись);
ЗаписьТекста = Новый ЗаписьДанных(ПотокЗаписи, КодировкаТекста.UTF8);
БуферТекста = ЧтениеТекста.Прочитать(50*1024*1024); // Делим по 50 мегабайт
ТекущаяПорция = Неопределено;
ПерваяСтрокаСчитана = Ложь;
Пока БуферТекста <> Неопределено Цикл 
	Если ТекущаяПорция <> Неопределено Тогда
		ЗаписьТекста.ЗаписатьСимволы(ТекущаяПорция, КодировкаТекста.UTF8);
		ЗаписьТекста.СброситьБуферы();
	КонецЕсли;
	Если Не ПерваяСтрокаСчитана Тогда
		БуферТекста = Прав(БуферТекста, СтрДлина(БуферТекста) - 15);
		ПерваяСтрокаСчитана = Истина;
	КонецЕсли;
	Если Прав(БуферТекста, 1) = """" Тогда
		// В конце нашли одинокую кавычку, надо её удалить
		БуферТекста = Лев(БуферТекста, СтрДлина(БуферТекста) - 1);
	КонецЕсли;
	ТекущаяПорция = СтрЗаменить(БуферТекста, """""", """");
	БуферТекста = ЧтениеТекста.Прочитать(ДелитьПо);
КонецЦикла;
Если ТекущаяПорция <> Неопределено Тогда
	ТекущаяПорция = СтрЗаменить(ТекущаяПорция, """}", "");
	ЗаписьТекста.ЗаписатьСимволы(ТекущаяПорция, КодировкаТекста.UTF8);
КонецЕсли;
ЧтениеТекста.Закрыть();
ПотокЧтения.Закрыть();
ЗаписьТекста.Закрыть();
ПотокЗаписи.Закрыть();

6) Profit! На выходе мы получаем файл имеющий в точности то же содержимое, что и положили в Хранилище значение. Тут можно и сразу в память считывать порцию данных из файла и в порции производить все замены, но так как мне дальше не обязательно держать в памяти именно строкой всю XML и для ещё большей оптимизации, решил делать запись в файл и его потом уже подавать процедуре чтения сообщения обмена.

7) Так же не забывайте убирать за собой, помогите сборщику мусора 1С, донесите свой мусор хотя бы до помойки:

Мусор = Неопределено;

Как и писалось в анонсе, данный способ не претендует на использование в продакшене (хотя мы у себя впилили, вместо ХранилищеЗначение.Получить() на проде), но надеюсь, данная публикация вам поможет, когда нужно через хранилище значения, передать много данных, а штатный механизм прожорлив или вообще падает (как в моём случае). Разумеется, вы бы сделали лучше чем я и код фактически один большой костыль. 

Тем же, кто думает о своей реализации обмена данными через веб-сервис, я бы пожалуй посоветовал паковку в ZIP архив на сервере (можно даже в памяти это сделать, без записи на диск) и передавать двоичные данные, а на клиенте уже сохранить полученные двоичные данные на диск, а дальше можно использовать типовой механизм.

Выражаю благодарность автору обработки, которая сделала сказку - былью!
Если у вас есть лишние помидоры и яйца, то вспомните о голодающих ;)

PS: Прошу обратить внимание на то, что данная публикация, получает строку, помещенную в хранилище значение, если вы хотите таким образов получать другие типы данных помещенные в хранилище значение, вам явно придется вооружится напильником, но нет ничего не возможного!

PS: Так же надо учитывать, что данный способ медленней чем штатный способ получения значения! Обратите так же внимание, тестировать обработку лучше в файловой базе или хотя бы на 32-х битном сервере 1С, где есть техническое ограничение на потребляемую память. На 64-х битном сервере 1С, даже очень большие данные сможет получить. Да, обработка не демонстрирует проблему, а демонстрирует решение.

ХранилищеЗначения ХранилищеЗначения.Получить(); Вылетает

См. также

SALE! 10%

Перенос данных из УПП 1.3 в ERP 2 / УТ 11 / КА 2. Переносятся документы, справочная информация и остатки

Обмен между базами 1C Платформа 1С v8.3 1С:Управление производственным предприятием 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Платные (руб)

Обработка позволяет перенести из УПП 1.3 в ERP / УТ 11 / КА 2 всю возможную информацию. Переносятся документы, а также начальные остатки и справочная информация. Есть фильтр по организации и множество других опциональных параметров выгрузки. Наши правила переноса в продаже с 2015 года, постоянно работаем над их развитием. Более 360 предприятий выполнили переход с использованием этого продукта. Оказываем техническую поддержку по всем вопросам проекта переноса данных из УПП 1.3.

50722 45650 руб.

04.08.2015    159283    363    266    

345

SALE! 10%

[ED3] Обмен для ERP 2.5, КА 2.5, УТ 11.5 БП 3.0, Розница, УНФ и других с EnterpriseData (универсальный формат обмена), правила обмена

Обмен между базами 1C Файловый обмен (TXT, XML, DBF), FTP Платформа 1С v8.3 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Россия Платные (руб)

Правила в универсальном формате обмена для ERP 2.5, КА 2.5, УТ 11.5, БП 3.0, Розница, УНФ, для последних версий конфигураций. Ссылки на другие конфигурации в описании публикации. Правила совместимы со всеми другими версиями конфигураций новыми и старыми, поддерживающими обмен в формате EnterpriseData. Не требуется синхронного обновления правил после обновления другой конфигурации, участвующей в обмене. Типовой обмен через планы обмена кнопкой Синхронизация вручную или автоматически по расписанию, или вручную обработкой.

25080 руб.

12.06.2017    134612    718    291    

387

Перенос данных из УПП 1.3 в БП 3.0. Переносятся документы (обороты за период), справочная информация и остатки

Обмен между базами 1C Файловый обмен (TXT, XML, DBF), FTP Платформа 1С v8.3 1С:Управление производственным предприятием 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Управленческий учет Платные (руб)

Перенос данных из 1С:Управление производственным предприятием 1.3 в 1С:Бухгалтерия предприятия 3.0 с помощью правил обмена. Переносятся остатки, документы (обороты за период), справочная информация. Правила проверены на конфигурациях УПП 1.3 (1.3.223.x) и БП 3.0 (3.0.149.x). Правила подходят для версии ПРОФ и КОРП.

28000 руб.

15.12.2021    20091    132    38    

90

SALE! 10%

Перенос данных из БП 3.0 в УТ 11 / КА 2 / ERP 2

Обмен между базами 1C Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Платные (руб)

Переносятся документы за выбранный период, нормативно-справочная информация и остатки по счетам бухгалтерского учета из программы "1С:БП 3.0" в "1С:УТ 11" или "1С:КА. 2" или "1С:ERP Управление предприятием, ред. 2".

29673 руб.

31.10.2014    231101    124    326    

295

SALE! 10%

Перенос данных из ERP 2 / КА 2 в ЗУП 3

Обмен между базами 1C Файловый обмен (TXT, XML, DBF), FTP Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Россия Бухгалтерский учет Управленческий учет Платные (руб)

Обработка позволяет не только перенести все документы, справочную информацию и начальные остатки из ERP 2 или КА 2 в ЗУП 3, но и организовать регулярный перенос данных между программами 1С:ERP 2 / КА 2 и 1С:ЗУП 3. Вы можете выбрать период отбора данных и установить фильтр по организациям, чтобы выгружать только необходимую информацию. Более того, перенос оперативно обновляется при выходе новых релизов программы 1С, так что вы всегда будете иметь самую актуальную версию обработки.

48278 43450 руб.

03.12.2020    34038    80    57    

78

SALE! 10%

Перенос данных из ERP 2 / КА 2 / УТ 11 в БП 3.0

Обмен между базами 1C Файловый обмен (TXT, XML, DBF), FTP Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Платные (руб)

Перенос позволяет настроить собственный обмен данными между указанными программами, альтернативный предлагаемому фирмой 1С. Перенос данных осуществляется из 1С:ERP 2 / 1С:КА 2 / 1С:УТ 11 в 1С:БП 3.0. Правила обмена оперативно обновляются при выходе новых релизов программы 1С, так что вы всегда будете иметь самую актуальную версию обработки.

38500 34650 руб.

15.04.2019    68202    176    136    

108

Перенос данных из Парус 10 в ЗГУ ред.3

Внешние источники данных Кадровый учет Файловый обмен (TXT, XML, DBF), FTP Обмен между базами 1C Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

Обработка позволяет перенести кадровую информацию и данные по заработной плате, фактических удержаниях, НДФЛ, вычетах, страховых взносах из базы Парус 10 учреждений в конфигурацию 1С:Зарплата и кадры государственного учреждения ред. 3 (ЗГУ) и начать с ней работать с любого месяца года.

60000 руб.

05.10.2022    9156    9    8    

10

Перенос данных из УТ 10.3 в УТ 11.5. Переносятся документы (обороты за период), справочная информация и остатки

Обмен между базами 1C Файловый обмен (TXT, XML, DBF), FTP Платформа 1С v8.3 Оперативный учет 1С:Управление торговлей 10 1С:Управление торговлей 11 Россия Управленческий учет Платные (руб)

Перенос данных из 1С:Управление торговлей 10.3 в 1С:Управление торговлей 11.5 с помощью правил обмена. Переносятся остатки, документы (обороты за период), справочная информация. Правила проверены на конфигурациях УТ 10.3 (10.3.87.x) и УТ 11.5 (11.5.16.x).

28000 руб.

23.07.2020    46025    194    64    

153
Оставьте свое сообщение