Как в 1С удалить лишние символы в начале бинарного файла без повреждения структуры

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Нередко при интеграции со сторонними веб-сервисами файлы выгрузки (например, отчеты в формате Excel) приходят с дефектами. Сервер может ошибочно дописать в самое начало ответа технические заголовки, фрагменты JavaScript или мусорные байты. В результате табличный документ перестает открываться в Excel и других программах.

Попытка обработать такой файл стандартными текстовыми средствами 1С (через ЧтениеТекста и ЗаписьТекста) приводит к фатальному повреждению данных. Разберем по шагам, почему это происходит и как правильно решить задачу штатными механизмами платформы 1С:Предприятие.

Почему текстовые объекты 1С портят двоичные файлы

Проанализируем механику работы текстовых объектов платформы. Когда мы пытаемся прочитать произвольный файл через ЧтениеТекста, платформа применяет к сырым байтам строковую логику:

  1. Необратимая подмена байтов кодовой страницей: При указании текстовой кодировки (например, КодировкаТекста.ANSI) байты сопоставляются с символами локальной таблицы Windows-1251. Нулевые байты (0x00) и специфические управляющие последовательности, встречающиеся в упакованных структурах Excel, не имеют корректного отображения и либо отсекаются, либо заменяются символами неопределенного знака.
  2. Автоматическая нормализация переводов строк: В бинарных данных байты 0x0D (CR) и 0x0A (LF) встречаются произвольно. Текстовые объекты воспринимают их как символы переноса строк и пытаются конвертировать (например, добавляя или убирая возврат каретки), что полностью разрушает контрольные суммы и структуру архивов XLSX или бинарных книг XLS.

Файлы таблиц Excel (как современные форматы XLSX/ZIP, так и старый формат XLS) являются строго двоичными, поэтому работать с ними нужно исключительно через бинарные потоки и объекты.

Способ 1. Использование потоков ЧтениеДанных и ЗаписьДанных (рекомендуемый)

Начиная с версии платформы 8.3.9, в 1С появились специализированные объекты для прямой работы с бинарными потоками данных без необходимости загружать весь файл в оперативную память. Это самый быстрый, надежный и кроссплатформенный способ обрезки начальных байтов.

Рассмотрим пример кода, где мы открываем исходный файл, пропускаем заданное количество мусорных байт и сохраняем чистые двоичные данные в целевой файл:


ПутьКИсходномуФайлу = "C:\temp\damaged_report.xlsx";
ПутьКИсправленному = "C:\temp\clean_report.xlsx";
КоличествоБайтДляУдаления = 57; // Точный размер мусорного заголовка в байтах

Чтение = Новый ЧтениеДанных(ПутьКИсходномуФайлу);
Запись = Новый ЗаписьДанных(ПутьКИсправленному);

// Пропускаем заданное смещение от начала
Чтение.Пропустить(КоличествоБайтДляУдаления);

// Передаем оставшиеся байты напрямую в целевой поток
Чтение.ИсходныйПоток().КопироватьВ(Запись.ЦелевойПоток());

Чтение.Закрыть();
Запись.Закрыть();

Преимущество этого метода заключается в том, что он одинаково стабильно работает на серверах под управлением как Windows, так и Linux, потребляет минимум оперативной памяти и не выполняет лишних преобразований данных.

Способ 2. Обрезка через Base64-кодирование (для старых конфигураций)

Если код выполняется в среде, где прямая работа с потоками данных недоступна, можно использовать встроенную сериализацию через ДвоичныеДанные и функции Base64. Однако здесь важно учитывать алгоритмические особенности кодирования.

Алгоритм Base64 кодирует каждые 3 байта исходных данных в 4 символа строки. Поэтому при обрезке строки Base64 длина удаляемого фрагмента должна быть строго кратна 4 символам, иначе битовые маски сместятся и файл окажется поврежден.

Посмотрим на реализацию данного подхода:


ДД = Новый ДвоичныеДанные(ПутьКИсходномуФайлу);

// Преобразуем бинарные данные в строковое представление
Строка64 = Base64Строка(ДД);

// Вычисляем количество удаляемых символов Base64
// Для 57 байт заголовка: 57 / 3 * 4 = 76 символов Base64
КоличествоСимволовBase64 = 76;

ОчищеннаяСтрока64 = Сред(Строка64, КоличествоСимволовBase64 + 1);

// Преобразуем строку обратно в двоичные данные и сохраняем
НовДД = Base64Значение(ОчищеннаяСтрока64);
НовДД.Записать(ПутьКИсправленному);

Важный момент: данный метод требует загрузки всего содержимого файла в память в виде строки (размер которой примерно на 33% больше исходного файла), поэтому его не рекомендуется применять для файлов большого объема (более 50–100 Мб).

Автоматическое определение смещения по сигнатурам файлов Excel

Если веб-сервер возвращает заголовок переменной длины, фиксированное число байт для пропуска указывать нельзя. В таком случае надежнее программно найти сигнатуру (магические числа) начала файла Excel:

  1. Формат XLSX: представляет собой ZIP-архив и всегда начинается с 4 байт сигнатуры PK-архива: 50 4B 03 04.
  2. Формат XLS: представляет собой OLE-контейнер и начинается с 8 байт: D0 CF 11 E0 A1 B1 1A E1.

Считав первые несколько килобайт в БуферДвоичныхДанных, можно определить точную позицию первого байта сигнатуры Excel и передать полученный индекс в метод Пропустить() объекта ЧтениеДанных.

← На главную