При выгрузке зашифрованных строк, бинарных данных или текстовых фрагментов со служебными символами разработчики нередко сталкиваются с ситуацией, когда данные в результирующем файле искажаются, обрезаются либо вызывают ошибку при записи. Попытки изменить формат ячейки в Excel на текстовый или заключить строку в блок XML не приносят результата. Разберем причины такого поведения и рассмотрим надежные способы сохранения произвольных данных в платформе 1С:Предприятие.
Выясним причину, по которой прямое сохранение непечатаемых символов невозможно на уровне стандартов:
0 до 31 (за исключением символов с кодом 9 — табуляция, 10 — перевод строки, 13 — возврат каретки). Символы NUL (0), Backspace (8), Escape (27) и ряд других являются недопустимыми в XML.CDATA внутри XML не позволяет передавать запрещенные управляющие коды стандарта 1.0. При попытке записать строку через объект ЗаписьXML платформа генерирует исключение о наличии недопустимого символа.Если данные необходимо передать или сохранить именно в текстовом формате (включая ячейки Excel, атрибуты XML или JSON), наиболее универсальным подходом является преобразование двоичных данных в безопасную строку Base64. Символы Base64 гарантированно входят в базовый печатный диапазон ASCII.
Посмотрим на пример упаковки произвольных двоичных данных в строку Base64 и обратного чтения:
// Преобразуем двоичные данные или строку в безопасный формат Base64
Двоичные = ПолучитьДвоичныеДанныеИзСтроки(ИсходнаяСтрока, КодировкаТекста.UTF8);
БезопаснаяСтрока = Base64Строка(Двоичные);
// Полученную строку можно безопасно записать в ячейку Excel или в XML
// Обратное чтение:
ВосстановленныеДвоичные = Base64Значение(БезопаснаяСтрока);
ИсходныйТекст = ПолучитьСтрокуИзДвоичныхДанных(ВосстановленныеДвоичные, КодировкаТекста.UTF8);
Альтернативой Base64 является прямое шестнадцатеричное кодирование (Hex), при котором каждый байт данных представляется парой печатных символов от 0 до F. Это исключает путаницу с разделителями и длинами кодов.
Рассмотрим использование встроенных платформенных функций 1С для работы с Hex:
// Кодирование двоичных данных в шестнадцатеричную строку
ДвоичныеДанныеФайла = ПолучитьДвоичныеДанныеИзСтроки(ЗакодированнаяСтрока);
HexСтрока = ПолучитьHexСтрокуИзДвоичныхДанных(ДвоичныеДанныеФайла);
// Запись Hex-строки в ячейку таблицы или XML-файл полностью безопасна
// Обратное восстановление двоичных данных:
ИсходныеДанные = ПолучитьДвоичныеДанныеИзHexСтроки(HexСтрока);
Проанализируем ситуацию, когда необходимо сохранить общую читаемость текста, экранировав только спецсимволы и непечатаемые коды. В платформе 1С для этого предусмотрены специализированные функции кодирования строк.
Разберем по шагам применение URL-кодирования:
// Кодирование строки: печатные символы сохраняются, непечатаемые заменяются на %XX
ЗащищенныйТекст = КодироватьСтроку(ИсходныйТекст, СпособКодированияСтроки.КодировкаURL);
// Защищенный текст сохраняется в Excel или XML без повреждения структуры
// Обратное декодирование:
ОригинальныйТекст = РаскодироватьСтроку(ЗащищенныйТекст, СпособКодированияСтроки.КодировкаURL);
Если выгрузка осуществляется в обычный текстовый файл через объект ЗаписьТекста, искажение символов (появление знаков ?) чаще всего вызвано неверным выбором кодовой страницы. Например, западноевропейская кодировка ISO-8859-1 не содержит кириллических глифов и заменяет их вопросительными знаками.
Посмотрим на пример правильной записи текстового файла с использованием Юникода:
// Для сохранения всех символов Юникода всегда используем UTF-8 или UTF-16
Запись = Новый ЗаписьТекста("C:\SafeExport.txt", КодировкаТекста.UTF8,,, Символы.ПС);
Запись.Записать(ЗакодированныйТекст);
Запись.Закрыть();
// Чтение файла выполняется с указанием той же кодировки:
Чтение = Новый ЧтениеТекста("C:\SafeExport.txt", КодировкаТекста.UTF8);
ПрочитанныйТекст = Чтение.Прочитать();
Чтение.Закрыть();
Когда данные представляют собой результат криптографического преобразования, хэш-суммы или упакованные структуры, преобразовывать их в строковый вид не требуется. Оптимальным решением является прямое сохранение объекта ДвоичныеДанные на диск.
// Сохранение бинарного буфера в файл без искажений
ДвоичныеДанныеБуфера.Записать("C:\Data.bin");
// Для побайтовой работы с потоками можно использовать ЗаписьДанных:
ФайловыйПоток = Новый ФайловыйПоток("C:\StreamData.bin", РежимОткрытияФайла.Создать);
ЗаписьПотока = Новый ЗаписьДанных(ФайловыйПоток);
ЗаписьПотока.Записать(ДвоичныеДанныеБуфера);
ЗаписьПотока.Закрыть();
Резюме: для сохранения произвольных непечатаемых символов и бинарных данных в форматах Excel и XML всегда используйте промежуточную сериализацию в Base64 или Hex. Для текстовых файлов применяйте КодировкаТекста.UTF8, а сырые зашифрованные данные храните в бинарных потоках без строковых преобразований.