Примеры работы с zip-архивами

Примеры работы с zip-архивами на языке программирования 1С:Предприятие. Примеры позволяют быстро разобраться в вопросе и использовать код в своих разработках

Создание ZIP-архива и добавление файлов

// Создание нового ZIP-архива и добавление в него файлов
Процедура СоздатьZipАрхив()

    // Путь к создаваемому архиву
    ПутьКАрхиву = "C:\Temp\МойАрхив.zip";
    
    // Создаем новый ZIP-архив
    ZipАрхив = Новый ZipЗапись(ПутьКАрхиву);
    
    // Добавляем текстовый файл из строки
    ZipАрхив.Добавить("Приветствие.txt", "Здравствуй, мир!" + Символы.ПС + "Это тестовое содержимое");
    
    // Добавляем файл из существующего файла на диске
    // (предварительно создадим тестовый файл)
    ТестовыйФайл = "C:\Temp\test.txt";
    ЗаписьТекста = Новый ЗаписьТекста(ТестовыйФайл, КодировкаТекста.UTF8);
    ЗаписьТекста.ЗаписатьСтроку("Тестовые данные для архива");
    ЗаписьТекста.Закрыть();
    
    ZipАрхив.Добавить("test.txt", ТестовыйФайл);
    
    // Добавляем файл с указанием кодировки имени в архиве
    ZipАрхив.Добавить("Документ.docx", "C:\Temp\document.docx", КодировкаТекста.UTF8);
    
    // Завершаем запись архива
    ZipАрхив.Записать();
    ZipАрхив.Закрыть();
    
    Сообщить("ZIP-архив создан: " + ПутьКАрхиву);
    
    // Проверяем существование архива
    Если ФайлСуществует(ПутьКАрхиву) Тогда
        Инфо = Новый ИнформацияОФайле(ПутьКАрхиву);
        Сообщить("Размер архива: " + Инфо.Размер + " байт");
    КонецЕсли;
    
КонецПроцедуры

Чтение содержимого ZIP-архива и извлечение файлов

// Открытие ZIP-архива, просмотр содержимого и извлечение файлов
Процедура ЧтениеZipАрхива()

    ПутьКАрхиву = "C:\Temp\МойАрхив.zip";
    ПутьДляИзвлечения = "C:\Temp\Extracted\";
    
    // Проверяем существование архива
    Если Не ФайлСуществует(ПутьКАрхиву) Тогда
        Сообщить("Архив не найден: " + ПутьКАрхиву);
        Возврат;
    КонецЕсли;
    
    // Создаем каталог для извлечения, если его нет
    Если Не КаталогСуществует(ПутьДляИзвлечения) Тогда
        СоздатьКаталог(ПутьДляИзвлечения);
    КонецЕсли;
    
    // Открываем ZIP-архив для чтения
    ЧтениеZip = Новый ZipЧтение(ПутьКАрхиву);
    
    // Получаем список файлов в архиве
    ФайлыВАрхиве = ЧтениеZip.Элементы;
    
    Сообщить("Содержимое архива '" + ПутьКАрхиву + "':");
    Сообщить("Всего элементов: " + ФайлыВАрхиве.Количество());
    
    // Перебираем все элементы архива
    Для Каждого Элемент Из ФайлыВАрхиве Цикл
        Если Элемент.ЭтоFolder Тогда
            Сообщить("[ПАПКА] " + Элемент.Имя + " (размер: " + Элемент.Размер + ")");
        Иначе
            Сообщить("[ФАЙЛ] " + Элемент.Имя + " (размер: " + Элемент.Размер + " байт)");
            
            // Извлекаем файл
            ПутьИзвлеченногоФайла = ПутьДляИзвлечения + Элемент.Имя;
            ЧтениеZip.Извлечь(Элемент, ПутьИзвлеченногоФайла);
            Сообщить("  -> извлечен в: " + ПутьИзвлеченногоФайла);
        КонецЕсли;
    КонецЦикла;
    
    // Закрываем архив
    ЧтениеZip.Закрыть();
    
    Сообщить("Извлечение завершено");
    
КонецПроцедуры

Добавление файлов с сохранением структуры папок

// Добавление файлов в ZIP-архив с сохранением
// иерархической структуры каталогов
Процедура ДобавитьФайлСоСтруктуройПапок()

    ПутьКАрхиву = "C:\Temp\СтруктурированныйАрхив.zip";
    КорневаяПапка = "C:\Temp\Source\";
    
    // Создаем тестовую структуру папок и файлов
    СоздатьТестовуюСтруктуру(КорневаяПапка);
    
    // Создаем архив
    ZipАрхив = Новый ZipЗапись(ПутьКАрхиву);
    
    // Функция рекурсивного обхода папок и добавления файлов
    Процедура ДобавитьПапкуВАрхив(ПутьПапки, ОтносительныйПуть, ZipАрхив)
        НайтиФайлы = Новый НайтиФайлы;
        НайтиФайлы.НайтиФайлы(ПутьПапки, "*", Истина);
        
        Для Каждого Файл Из НайтиФайлы.Файлы Цикл
            // Формируем путь внутри архива
            ПутьВАрхиве = ОтносительныйПуть + Файл.Имя;
            ZipАрхив.Добавить(ПутьВАрхиве, Файл.ПолноеИмя);
            Сообщить("Добавлен файл: " + ПутьВАрхиве);
        КонецЦикла;
        
        // Обрабатываем вложенные папки
        НайтиПапки = Новый НайтиФайлы;
        НайтиПапки.НайтиФайлы(ПутьПапки, "*", Истина);
        
        Для Каждого Папка Из НайтиПапки.Папки Цикл
            НовыйОтносительныйПуть = ОтносительныйПуть + Папка.Имя + "/";
            ДобавитьПапкуВАрхив(Папка.ПолноеИмя, НовыйОтносительныйПуть, ZipАрхив);
        КонецЦикла;
    КонецПроцедуры
    
    // Запускаем обход
    ДобавитьПапкуВАрхив(КорневаяПапка, "", ZipАрхив);
    
    // Завершаем запись
    ZipАрхив.Записать();
    ZipАрхив.Закрыть();
    
    Сообщить("Архив со структурой создан: " + ПутьКАрхиву);
    
КонецПроцедуры

Процедура СоздатьТестовуюСтруктуру(КорневаяПапка)
    Если Не КаталогСуществует(КорневаяПапка + "Папка1\") Тогда
        СоздатьКаталог(КорневаяПапка + "Папка1\");
    КонецЕсли;
    
    Запись = Новый ЗаписьТекста(КорневаяПапка + "Папка1\файл1.txt", КодировкаТекста.UTF8);
    Запись.ЗаписатьСтроку("Содержимое файла 1");
    Запись.Закрыть();
    
    Если Не КаталогСуществует(КорневаяПапка + "Папка1\Папка2\") Тогда
        СоздатьКаталог(КорневаяПапка + "Папка1\Папка2\");
    КонецЕсли;
    
    Запись = Новый ЗаписьТекста(КорневаяПапка + "Папка1\Папка2\файл2.txt", КодировкаТекста.UTF8);
    Запись.ЗаписатьСтроку("Содержимое файла 2");
    Запись.Закрыть();
КонецПроцедуры

Обработка ошибок при работе с ZIP-архивами

// Безопасная работа с ZIP-архивами с обработкой возможных ошибок
Процедура БезопаснаяРаботаСZip()

    ПутьКАрхиву = "C:\Temp\НесуществующийАрхив.zip";
    ПутьДляИзвлечения = "C:\Temp\Extract\";
    
    // Проверка существования архива перед открытием
    Если Не ФайлСуществует(ПутьКАрхиву) Тогда
        Сообщить("Ошибка: файл не существует - " + ПутьКАрхиву);
        Возврат;
    КонецЕсли;
    
    // Создание каталога для извлечения с проверкой
    Если Не КаталогСуществует(ПутьДляИзвлечения) Тогда
        Попытка
            СоздатьКаталог(ПутьДляИзвлечения);
        Исключение
            Сообщить("Не удалось создать каталог: " + ОписаниеОшибки());
            Возврат;
        КонецПопытки;
    КонецЕсли;
    
    // Открытие архива с обработкой ошибок
    Попытка
        ЧтениеZip = Новый ZipЧтение(ПутьКАрхиву);
    Исключение
        Сообщить("Ошибка открытия архива: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;
    
    // Проверка, что архив не поврежден
    Попытка
        ФайлыВАрхиве = ЧтениеZip.Элементы;
        Если ФайлыВАрхиве.Количество() = 0 Тогда
            Сообщить("Архив пуст");
        КонецЕсли;
    Исключение
        Сообщить("Ошибка чтения содержимого архива: " + ОписаниеОшибки());
        ЧтениеZip.Закрыть();
        Возврат;
    КонецПопытки;
    
    // Извлечение файлов с проверкой свободного места
    СвободноеМесто = ВычислитьСвободноеМесто(ПутьДляИзвлечения);
    ОбщийРазмер = 0;
    
    Для Каждого Элемент Из ФайлыВАрхиве Цикл
        Если Не Элемент.ЭтоFolder Тогда
            ОбщийРазмер = ОбщийРазмер + Элемент.Размер;
        КонецЕсли;
    КонецЦикла;
    
    Если ОбщийРазмер > СвободноеМесто Тогда
        Сообщить("Недостаточно свободного места на диске. Требуется: " + 
                 Строка(ОбщийРазмер) + " байт, доступно: " + Строка(СвободноеМесто) + " байт");
        ЧтениеZip.Закрыть();
        Возврат;
    КонецЕсли;
    
    // Извлечение файлов
    КоличествоИзвлеченных = 0;
    Для Каждого Элемент Из ФайлыВАрхиве Цикл
        Если Не Элемент.ЭтоFolder Тогда
            Попытка
                ПутьИзвлечения = ПутьДляИзвлечения + Элемент.Имя;
                ЧтениеZip.Извлечь(Элемент, ПутьИзвлечения);
                КоличествоИзвлеченных = КоличествоИзвлеченных + 1;
                Сообщить("Извлечен: " + Элемент.Имя);
            Исключение
                Сообщить("Ошибка извлечения файла " + Элемент.Имя + ": " + ОписаниеОшибки());
            КонецПопытки;
        КонецЕсли;
    КонецЦикла;
    
    ЧтениеZip.Закрыть();
    
    Сообщить("Извлечено файлов: " + Строка(КоличествоИзвлеченных) + 
             " из " + Строка(ФайлыВАрхиве.Количество()));
    
КонецПроцедуры

Функция ВычислитьСвободноеМесто(Путь)
    // Упрощенная эмуляция получения свободного места
    Возврат 1000000000; // 1 ГБ (в реальном коде нужно использовать API системы)
КонецФункции

Создание ZIP-архива из таблицы файлов (пакетная обработка)

// Пакетное добавление файлов в архив из таблицы значений
Процедура СоздатьАрхивИзТаблицыФайлов()

    // Создаем таблицу с перечнем файлов для архивации
    ТаблицаФайлов = Новый ТаблицаЗначений;
    ТаблицаФайлов.Колонки.Добавить("ПутьКФайлу");
    ТаблицаФайлов.Колонки.Добавить("ИмяВАрхиве");
    ТаблицаФайлов.Колонки.Добавить("ПапкаВАрхиве");
    
    // Заполняем тестовыми данными
    Для Инд = 1 По 5 Цикл
        ИмяФайла = "C:\Temp\file" + Строка(Инд) + ".txt";
        Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8);
        Запись.ЗаписатьСтроку("Содержимое файла " + Строка(Инд));
        Запись.Закрыть();
        
        НоваяСтрока = ТаблицаФайлов.Добавить();
        НоваяСтрока.ПутьКФайлу = ИмяФайла;
        НоваяСтрока.ИмяВАрхиве = "file" + Строка(Инд) + ".txt";
        НоваяСтрока.ПапкаВАрхиве = "Документы/Загрузки/";
    КонецЦикла;
    
    // Создаем архив
    ПутьКАрхиву = "C:\Temp\АрхивИзТаблицы_" + Формат(ТекущаяДата(), "ДФ=yyyyMMddHHmmss") + ".zip";
    ZipАрхив = Новый ZipЗапись(ПутьКАрхиву);
    
    // Добавляем файлы из таблицы
    Для Каждого СтрокаФайла Из ТаблицаФайлов Цикл
        // Проверяем существование файла
        Если ФайлСуществует(СтрокаФайла.ПутьКФайлу) Тогда
            // Формируем полный путь внутри архива
            ПолныйПутьВАрхиве = СтрокаФайла.ПапкаВАрхиве + СтрокаФайла.ИмяВАрхиве;
            ZipАрхив.Добавить(ПолныйПутьВАрхиве, СтрокаФайла.ПутьКФайлу);
            Сообщить("Добавлен: " + СтрокаФайла.ПутьКФайлу + " -> " + ПолныйПутьВАрхиве);
        Иначе
            Сообщить("Файл не найден: " + СтрокаФайла.ПутьКФайлу);
        КонецЕсли;
    КонецЦикла;
    
    // Завершаем запись
    Попытка
        ZipАрхив.Записать();
        ZipАрхив.Закрыть();
        Сообщить("Архив успешно создан: " + ПутьКАрхиву);
    Исключение
        Сообщить("Ошибка при создании архива: " + ОписаниеОшибки());
    КонецПопытки;
    
    // Получаем информацию о созданном архиве
    Если ФайлСуществует(ПутьКАрхиву) Тогда
        Инфо = Новый ИнформацияОФайле(ПутьКАрхиву);
        Сообщить("Размер архива: " + Инфо.Размер + " байт (" + 
                 Окр(Инфо.Размер / 1024, 2) + " КБ)");
    КонецЕсли;
    
КонецПроцедуры

Архивация с разбивкой на тома (многотомный архив)

// Создание ZIP-архива с автоматическим разбиением на части заданного размера
Процедура СоздатьМноготомныйZipАрхив()

    // Путь к исходному файлу (большой файл)
    БольшойФайл = "C:\Temp\BigFile.dat";
    РазмерПорции = 1024 * 1024; // 1 МБ
    
    // Создаем тестовый большой файл
    Запись = Новый ЗаписьТекста(БольшойФайл, КодировкаТекста.UTF8);
    Для Инд = 1 По 1000 Цикл
        Запись.ЗаписатьСтроку("Строка с данными номер " + Строка(Инд) + 
                             ". Здесь много текста для увеличения размера файла.");
    КонецЦикла;
    Запись.Закрыть();
    
    // Создаем архив
    БазовоеИмяАрхива = "C:\Temp\MultipartArchive.zip";
    НомерТома = 1;
    ТекущийРазмер = 0;
    
    ZipАрхив = Неопределено;
    
    // Функция открытия нового тома
    Процедура ОткрытьНовыйТом(БазовоеИмя, НомерТома)
        ИмяТома = СтрЗаменить(БазовоеИмя, ".zip", ".part" + Строка(НомерТома) + ".zip");
        Возврат Новый ZipЗапись(ИмяТома);
    КонецПроцедуры
    
    // Открываем первый том
    ТекущийАрхив = ОткрытьНовыйТом(БазовоеИмяАрхива, НомерТома);
    
    // Добавляем файл по частям (эмуляция)
    // В реальном коде нужно читать исходный файл порциями
    Для Порция = 1 По 5 Цикл
        // Добавляем в текущий том кусок данных
        ИмяВАрхиве = "BigFile_part" + Строка(Порция) + ".dat";
        Данные = "Тестовые данные для порции " + Строка(Порция);
        ТекущийАрхив.Добавить(ИмяВАрхиве, Данные);
        
        ТекущийРазмер = ТекущийРазмер + СтрДлина(Данные);
        
        // Если размер превысил лимит, создаем новый том
        Если ТекущийРазмер >= РазмерПорции Тогда
            ТекущийАрхив.Записать();
            ТекущийАрхив.Закрыть();
            
            НомерТома = НомерТома + 1;
            ТекущийАрхив = ОткрытьНовыйТом(БазовоеИмяАрхива, НомерТома);
            ТекущийРазмер = 0;
            
            Сообщить("Создан том #" + Строка(НомерТома - 1));
        КонецЕсли;
    КонецЦикла;
    
    // Закрываем последний том
    Если ТекущийАрхив <> Неопределено Тогда
        ТекущийАрхив.Записать();
        ТекущийАрхив.Закрыть();
        Сообщить("Создан последний том #" + Строка(НомерТома));
    КонецЕсли;
    
    // Информация о созданных томах
    Сообщить("Создано томов: " + Строка(НомерТома));
    Для Ном = 1 По НомерТома Цикл
        ИмяТома = СтрЗаменить(БазовоеИмяАрхива, ".zip", ".part" + Строка(Ном) + ".zip");
        Если ФайлСуществует(ИмяТома) Тогда
            Инфо = Новый ИнформацияОФайле(ИмяТома);
            Сообщить("Том " + Строка(Ном) + ": " + Инфо.Размер + " байт");
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Сжатие каталога с помощью рекурсивного обхода

// Полное сжатие выбранного каталога со всем содержимым
Процедура СжатьКаталогВZip(ПутьКаталога, ПутьАрхива = "")

    // Если путь архива не указан, создаем рядом с каталогом
    Если ПутьАрхива = "" Тогда
        ПутьАрхива = КаталогИзвлечения(ПутьКаталога) + ИмяКаталога(ПутьКаталога) + ".zip";
    КонецЕсли;
    
    // Проверяем существование каталога
    Если Не КаталогСуществует(ПутьКаталога) Тогда
        Сообщить("Каталог не найден: " + ПутьКаталога);
        Возврат;
    КонецЕсли;
    
    // Создаем архив
    Попытка
        ZipАрхив = Новый ZipЗапись(ПутьАрхива);
        
        // Рекурсивно добавляем все файлы
        ДобавитьКаталогВZip(ПутьКаталога, ZipАрхив, "");
        
        ZipАрхив.Записать();
        ZipАрхив.Закрыть();
        
        Сообщить("Каталог '" + ПутьКаталога + "' успешно сжат в '" + ПутьАрхива + "'");
        
    Исключение
        Сообщить("Ошибка при сжатии каталога: " + ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

Процедура ДобавитьКаталогВZip(ПутьКаталога, ZipАрхив, ОтносительныйПуть)
    
    // Обрабатываем файлы в текущем каталоге
    НайтиФайлы = Новый НайтиФайлы;
    НайтиФайлы.НайтиФайлы(ПутьКаталога, "*", Истина);
    
    Для Каждого Файл Из НайтиФайлы.Файлы Цикл
        // Формируем путь файла внутри архива
        ПутьВАрхиве = ОтносительныйПуть + Файл.Имя;
        
        // Добавляем файл в архив
        ZipАрхив.Добавить(ПутьВАрхиве, Файл.ПолноеИмя);
        Сообщить("Добавлен файл: " + ПутьВАрхиве);
    КонецЦикла;
    
    // Обрабатываем вложенные каталоги
    НайтиПапки = Новый НайтиФайлы;
    НайтиПапки.НайтиФайлы(ПутьКаталога, "*", Истина);
    
    Для Каждого Папка Из НайтиПапки.Папки Цикл
        // Рекурсивно обрабатываем каждую вложенную папку
        НовыйОтносительныйПуть = ОтносительныйПуть + Папка.Имя + "/";
        ДобавитьКаталогВZip(Папка.ПолноеИмя, ZipАрхив, НовыйОтносительныйПуть);
    КонецЦикла;
    
КонецПроцедуры

// Пример использования
Процедура ПримерСжатияКаталога()
    
    // Создаем тестовый каталог с файлами
    ТестовыйКаталог = "C:\Temp\TestCatalog\";
    Если Не КаталогСуществует(ТестовыйКаталог) Тогда
        СоздатьКаталог(ТестовыйКаталог);
    КонецЕсли;
    
    Для Инд = 1 По 3 Цикл
        ИмяФайла = ТестовыйКаталог + "file" + Строка(Инд) + ".txt";
        Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8);
        Запись.ЗаписатьСтроку("Содержимое файла " + Строка(Инд));
        Запись.Закрыть();
    КонецЦИКЛА;
    
    // Сжимаем каталог
    СжатьКаталогВZip(ТестовыйКаталог);
    
КонецПроцедуры

Примечания

// Важные особенности работы с ZIP-архивами в 1С:
// 1. Для работы с ZIP-архивами используются объекты ZipЗапись (создание) и ZipЧтение (чтение)
// 2. Обязательно закрывайте архив методами Записать() (для ZipЗапись) и Закрыть() (для обоих типов)
// 3. Метод Добавить() позволяет добавлять файлы как из существующих файлов, так и из строки данных
// 4. При чтении архива свойство Элементы возвращает коллекцию элементов (файлов и папок)
// 5. Проверяйте наличие архива и каталогов перед операциями во избежание ошибок
// 6. Используйте конструкцию Попытка...Исключение...КонецПопытки для обработки ошибок доступа
// 7. Вложенные папки в архиве создаются автоматически при указании пути с разделителями
// 8. Для рекурсивного добавления целых каталогов используйте НайтиФайлы и обход в глубину
// 9. ZIP-архивы в 1С не поддерживают шифрование и комментарии
// 10. Размер добавляемого файла ограничен доступной памятью и свободным местом на диске
// 11. При работе с большими файлами используйте пакетную обработку и контроль свободного места
// 12. Метод Извлечь() может перезаписывать существующие файлы без предупреждения - учитывайте это

Поделиться с друзьями
Smirnov code
Добавить комментарий