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

22.04.19

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

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

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
Альтернативное получение значения из хранилища значения. Свой ХранилищеЗначения.Получить();:
.epf 12,71Kb ver:0.1
14
14 Скачать (1 SM) Купить за 1 850 руб.

Однажды, когда я был молодой и глупый (последнее правда с тех под и не изменилось), я решал задачу автоматического РИБ обмена через веб-сервис и в качестве контейнера для данных, я решил использовать передачу хранилища значения, в котором упакована с сжатием (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%

Перенос данных 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. Не требуется синхронного обновления правил после обновления другой конфигурации, участвующей в обмене. Типовой обмен через планы обмена кнопкой Синхронизация вручную или автоматически по расписанию, или вручную обработкой.

27660 руб.

12.06.2017    143335    821    297    

428

SALE! 10%

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

Перенос документов, начальных остатков и справочной информации из УПП 1.3 в ERP 2 | из УПП 1.3 в УТ 11 | из УПП в КА 2 | Правила конвертации (КД 2) | Более 360 предприятий выполнили переход с использованием этого продукта! | Сэкономьте время - используйте готовое решение для перехода! | Позволяет перенести из УПП 1.3 в ERP / УТ 11 / КА 2 всю возможную информацию | В переносе есть фильтр по организации и множество других опциональных параметров выгрузки | Есть несколько алгоритмов выгрузки остатков на выбор

55778 50200 руб.

04.08.2015    168368    344    279    

380

SALE! 10%

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

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

35000 31500 руб.

23.07.2020    53431    236    73    

192

SALE! 10%

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

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

35000 31500 руб.

15.12.2021    24829    174    51    

132

SALE! 10%

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

Перенос данных из ERP в ЗУП 3 | из КА 2 в ЗУП | Готовые правила конвертации данных (КД 2) для переноса остатков, документов с движениями и справочной информации 3 | Есть перенос начальной задолженности по зарплате и начальной штатной расстановки на выбранную дату | Обороты за прошлые годы (данные для расчета среднего) переносятся свернуто в документ "Перенос данных" | Есть фильтр по организациям | Документы за текущий период переносятся сразу с движениями, поэтому не потребуется делать перерасчеты | Перенос можно проверить перед покупкой, обращайтесь!

53111 47800 руб.

03.12.2020    37250    99    66    

95

Перенос данных 1C Программист Бухгалтер Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и Управление Персоналом 3.x Россия Бухгалтерский учет НДФЛ ФОМС, ЕФС Платные (руб)

Обработки для быстрого перехода с конфигураций «КАМИН:Расчет заработной платы 3.0», «КАМИН:Зарплата для бизнеса 4.0» и «КАМИН:Зарплата 5.0» на конфигурацию «Зарплата и управление персоналом» версии 3.1.

12000 руб.

25.09.2016    81568    324    253    

276

SALE! 10%

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

Перенос данных из 1С:Управление производственным предприятием 1.3 в 1С:Бухгалтерия предприятия 3.0 с помощью правил обмена | Можно выполнить переход с УПП на БП 3 или запускать выгрузку данных за выбранный период времени | Переносятся документы, начальные остатки и вся справочная информация | Есть фильтр по организации и множество других параметров выгрузки | Поддерживается несколько сценариев работы: как первичный полный перенос, так и перенос только новых документов | Перенос данных возможен в "1С: Бухгалтерия 3.0" версии ПРОФ, КОРП или базовую | Переход с "1С: УПП1.3" / "1С:КА 1.1" на "1С:БП3.0" с помощью правил конвертации будет максимально комфортным! | Можно бесплатно проверить перенос на вашем сервере!

48278 43450 руб.

25.02.2015    172022    307    258    

384

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

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

120000 руб.

19.08.2020    25696    25    1    

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