При разработке систем обмена данными или систем контроля версий часто возникает задача обеспечения побитовой идентичности файлов. Одной из главных проблем здесь являются метаданные файловой системы: даты создания, последнего изменения и доступа. Если два файла идентичны по содержанию, но имеют разные даты, созданные на их основе ZIP-архивы могут отличаться по хеш-сумме. В этой статье мы подробно разберем, как управлять временными метками файлов в среде 1С и какие инструменты использовать для создания «зеркальных» архивов.
Для начала проанализируем возможности встроенного языка 1С. Платформа предоставляет объект Файл, у которого есть метод УстановитьВремяИзменения(). Рассмотрим пример его использования:
// Пример установки времени изменения файла штатными средствами
ПутьКФайлу = "C:\temp\data.xml";
ОбъектФайл = Новый Файл(ПутьКФайлу);
Если ОбъектФайл.Существует() Тогда
ТекущаяДатаУстановки = ТекущаяДата();
ОбъектФайл.УстановитьВремяИзменения(ТекущаяДатаУстановки);
КонецЕсли;
Важное ограничение: данный метод изменяет исключительно дату последнего изменения (Last Write Time). Даты создания (Creation Time) и последнего доступа (Last Access Time) остаются прежними. Как показывает практика, встроенный механизм ЗаписьZipФайла при упаковке может считывать расширенные атрибуты NTFS, включая все три временные метки. Если они различаются, итоговые ZIP-файлы не будут идентичны побайтово, даже если содержимое внутри совпадает.
Поскольку штатных средств 1С недостаточно для модификации всех атрибутов времени, мы можем воспользоваться возможностями операционной системы. Самым эффективным и современным способом является вызов PowerShell непосредственно из кода 1С. Это не требует регистрации внешних компонент и работает на большинстве современных серверов Windows.
Разберем алгоритм установки всех трех дат. Нам нужно сформировать строку команды и выполнить ее через ЗапуститьПриложение. Рассмотрим пример функции:
Процедура УстановитьВсеДатыФайла(ПутьКФайлу, НужнаяДата)
// Форматируем дату для PowerShell (гггг-мм-дд чч:мм:сс)
СтрокаДаты = Формат(НужнаяДата, "ДФ='yyyy-MM-dd HH:mm:ss'");
// Формируем команды PowerShell для трех типов дат
КомандаPS = СтрШаблон("(Get-Item '%1').CreationTime = '%2'; (Get-Item '%1').LastWriteTime = '%2'; (Get-Item '%1').LastAccessTime = '%2';",
ПутьКФайлу, СтрокаДаты);
// Выполняем команду через оболочку
ЗапускКоманды = "powershell -ExecutionPolicy Bypass -Command """ + КомандаPS + """";
ЗапуститьПриложение(ЗапускКоманды, , Истина); // Ждем завершения выполнения
КонецПроцедуры
Проанализируем ситуацию: использование -ExecutionPolicy Bypass позволяет обойти ограничения на запуск скриптов, а параметр Истина в методе ЗапуститьПриложение гарантирует, что 1С дождется завершения операции перед тем, как начнет архивировать файл.
Выясним причину, по которой архивы могут оставаться разными даже после программной установки дат. Исторически формат ZIP использует формат времени DOS (MS-DOS date/time), который имеет точность всего 2 секунды. Это означает, что если вы установите время файла 12:00:01, архиватор может округлить его до 12:00:00 или 12:00:02.
Чтобы гарантировать побитовую идентичность, придерживайтесь следующих правил:
Если ЗаписьZipФайла продолжает добавлять в архив метаданные, которые мешают идентичности (например, расширенные поля NTFS Extra Fields), рассмотрим использование консольной версии 7-Zip. Этот архиватор позволяет гибко управлять тем, какие атрибуты времени попадают в заголовок архива.
Для создания идентичных архивов мы можем использовать ключи командной строки:
-mtc=off — отключает запись времени создания файла.-mta=off — отключает запись времени последнего доступа.-mtm=on — оставляет только время модификации (стандарт для ZIP).Посмотрим на пример вызова из 1С:
КомандаАрхивации = """C:\Program Files\7-Zip\7z.exe"" a ""C:\temp\arch.zip"" ""C:\temp\data.xml"" -mtc=off -mta=off";
ЗапуститьПриложение(КомандаАрхивации, , Истина);
Этот метод является наиболее надежным «крайним вариантом», так как он полностью исключает влияние метаданных файловой системы на структуру ZIP-контейнера.
Для системных администраторов и разработчиков, работающих в среде Windows без возможности запуска PowerShell, существует вариант работы через COM-объект Shell.Application. Рассмотрим, как это выглядит:
Shell = Новый COMОбъект("Shell.Application");
Папка = Shell.NameSpace("C:\temp");
ФайлОбъект = Папка.ParseName("data.xml");
// Внимание: через этот объект удобно читать свойства,
// но прямая запись дат может потребовать работы с методом ModifyDate
ФайлОбъект.ModifyDate = '20230101120000';
Однако отметим, что данный способ менее гибок, чем PowerShell, и чаще используется для простых манипуляций с датой изменения или при работе со встроенными в Windows ZIP-папками.
Подводя итог нашему анализу, предложим оптимальный алгоритм для решения задачи:
ЗаписьZipФайла.Такой комплексный подход позволит вам избежать проблем с хеш-суммами и обеспечит стабильную работу механизмов синхронизации файлов в ваших проектах на платформе 1С.