Перевод ИТ-инфраструктуры 1С:Предприятие на операционные системы семейства Linux (например, CentOS, RedHat, Rocky Linux) в связке с СУБД PostgreSQL — это отличный шаг в сторону оптимизации затрат на лицензирование и повышения стабильности работы системы. Однако на этом пути часто возникают неожиданные проблемы совместимости, связанные с обработкой устаревших форматов файлов данных. Одна из самых распространенных неполадок — появление «иероглифов» или «кракозябр» при попытке прочитать классические файлы обмена DBF (например, файлы выгрузки клиент-банков) на стороне сервера Linux.
В этой статье мы подробно проанализируем причины этой проблемы, разберем, почему переустановка PostgreSQL или изменение кодировок баз данных здесь не помогут, и рассмотрим практические варианты решения проблемы как на уровне программирования 1С, так и на уровне системного администрирования операционной системы CentOS.
Первое заблуждение, с которым сталкиваются многие специалисты при возникновении проблем с кодировкой в трехзвенной архитектуре 1С, — это подозрения в сторону СУБД PostgreSQL. Администраторы начинают пересоздавать кластер баз данных под разные кодировки, пытаются принудительно внедрить локаль ru_RU.CP1251. Однако важно понимать ключевой принцип работы 1С с СУБД:
Таким образом, проблема кроется исключительно на этапе чтения файла сервером приложений 1С с использованием встроенного объекта XBase.
Для чтения файлов формата DBF в платформе 1С:Предприятие используется объект XBase. Когда в коде прописывается свойство КодировкаXBase.ANSI, это указывает платформе на необходимость трансляции исходных байтов из кодовой страницы Windows-1251 (CP1251) в формат Unicode (который используется внутри платформы 1С).
На операционной системе Windows эта трансляция происходит автоматически силами системных API. На операционной системе Linux платформа 1С вынуждена использовать системную библиотеку локализации glibc и ориентироваться на текущую локаль запущенного процесса. Если процесс сервера 1С (демон ragent) работает в окружении с дефолтной локалью C или POSIX (или в чисто англоязычной локали en_US.UTF-8), то в системе просто отсутствуют необходимые таблицы сопоставления для кодировки CP1251. В результате этого встроенные функции перевода кодировок отрабатывают неверно, выдавая кракозябры вместо кириллических символов.
Давайте разберем три основных способа решения этой проблемы.
Если в вашей компании пользователи работают с платформой 1С на операционной системе Windows, а сервер приложений крутится под управлением Linux, самым простым и надежным решением будет перенос операции чтения DBF-файла на сторону клиента. На клиентском компьютере Windows чтение кодировки CP1251 всегда отрабатывает корректно без дополнительных настроек ОС.
Рассмотрим по шагам, как это реализовать. Нам необходимо считать файл на клиенте, поместить данные во временную таблицу или структуру и передать эту таблицу на сервер для дальнейшей записи в базу данных.
Проанализируем пример кода, реализующий этот подход:
&НаСервере
Процедура ОбработатьДанныеНаСервере(ТаблицаДанных)
// Преобразуем реквизит формы в значение для серверной обработки
ТаблицаОбД = РеквизитФормыВЗначение("ТаблицаОбДанных");
ТаблицаОбД.Очистить();
Для Каждого СтрокаТЗ Из ТаблицаДанных Цикл
НоваяСтрока = ТаблицаОбД.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЗ);
КонецЦикла;
// Возвращаем данные обратно на форму
ЗначениеВРеквизитФормы(ТаблицаОбД, "ТаблицаОбДанных");
КонецПроцедуры
&НаКлиенте
Процедура ПрочитатьФайлНаКлиенте()
ФайлDBF = Новый XBase;
// Указываем кодировку ANSI (для кириллицы это CP1251)
ФайлDBF.Кодировка = КодировкаXBase.ANSI;
ПутьКФайлу = "C:\000.DBF";
Попытка
ФайлDBF.ОткрытьФайл(ПутьКФайлу, , Истина); // Открываем только для чтения
Исключение
ПоказатьПредупреждение(, "Не удалось открыть файл: " + ПутьКФайлу);
Возврат;
КонецПопытки;
// Создаем таблицу для передачи данных на сервер
ТаблицаПередачи = Новый ТаблицаЗначений;
ТаблицаПередачи.Колонки.Добавить("Поле1");
ТаблицаПередачи.Колонки.Добавить("Поле2");
ФайлDBF.Первая();
Пока Не ФайлDBF.ВКонце() Цикл
Если Не ФайлDBF.ЗаписьУдалена() Тогда
НоваяСтрока = ТаблицаПередачи.Добавить();
НоваяСтрока.Поле1 = ФайлDBF.POS;
НоваяСтрока.Поле2 = ФайлDBF.NNASP;
КонецЕсли;
ФайлDBF.Следующая();
КонецЦикла;
ФайлDBF.ЗакрытьФайл();
// Передаем собранные данные на сервер
ОбработатьДанныеНаСервере(ТаблицаПередачи);
КонецПроцедуры
Данный метод полностью исключает зависимость от настроек сервера Linux, так как вся низкоуровневая работа с DBF-форматом и кодировками происходит в гарантированно совместимой среде Windows.
Бывают ситуации, когда импорт DBF-файлов должен происходить в фоновом режиме (например, по расписанию через регламентное задание), когда никакого активного Windows-клиента нет. В этом случае нам придется заставить сервер 1С под Linux корректно понимать кириллическую кодировку ANSI.
Многие администраторы делают ошибку, настраивая локаль глобально через утилиту localectl set-locale LANG=ru_RU.cp1251. Сервер 1С запускается как системная служба через менеджер systemd, который изолирует переменные окружения и по умолчанию не передает глобальные настройки локали процессу ragent. Поэтому локаль нужно задать принудительно в конфигурационном юните службы 1С.
Разберем процесс настройки по шагам на примере CentOS:
locale -a | grep ru
В выводе вы должны увидеть строку ru_RU.utf8. Если ее нет, ее необходимо сгенерировать командой:
localedef -i ru_RU -f UTF-8 ru_RU.UTF-8
usr1cv8:
su -s /bin/bash -c "locale" usr1cv8
systemd:
systemctl edit srv1cv83.service
(Обратите внимание: имя службы может отличаться в зависимости от версии платформы, например, srv1cv83 или 1c-enterprise-8.3.22).
[Service]
Environment=LANG=ru_RU.UTF-8
Environment=LC_ALL=ru_RU.UTF-8
ru_RU.UTF-8 вполне достаточно — она содержит в себе все необходимые таблицы перекодирования для ANSI/CP1251.
systemd:
systemctl daemon-reload
systemctl restart srv1cv83.service
После выполнения этих шагов процесс сервера 1С получит доступ к таблицам перевода символов, и встроенный объект XBase на стороне сервера начнет корректно преобразовывать кириллицу из формата ANSI в Unicode.
При переносе кода работы с DBF на Linux-сервер часто возникает сопутствующая ошибка: "Ошибка открытия файла". Помните, что операционная система Linux чувствительна к регистру символов в путях и именах файлов (Case Sensitivity).
Если на диске ваш файл называется import.dbf, а в коде 1С вы обращаетесь к нему как Import.DBF, Linux-сервер не сможет его найти и вызовет исключение. Всегда приводите имена файлов и пути к ним к точному соответствию на файловой системе.
Если у вас нет доступа к административным настройкам операционной системы сервера Linux, а загрузка должна выполняться на сервере, можно воспользоваться сторонними утилитами конвертации. Однако напрямую использовать популярную утилиту iconv для конвертации DBF-файла нельзя, так как DBF содержит бинарный заголовок, повреждение которого сделает файл нечитаемым.
Решением может стать написание небольшого скрипта на Python с использованием библиотеки dbfread или dbf, который будет предварительно читать DBF, переводить текстовые поля в UTF-8 и сохранять данные во временный текстовый файл (например, CSV или JSON) в кодировке UTF-8. Затем сервер 1С сможет легко прочитать этот текстовый файл с помощью объекта ЧтениеТекста, где кодировка указывается явно при чтении.
Подведем итог: для исправления кракозябр при чтении DBF на сервере 1С под Linux лучшим программистским решением является перенос разбора файла на сторону Windows-клиента, а лучшим системным решением — прописывание корректных переменных окружения LANG=ru_RU.UTF-8 в юнит службы 1С в systemd.