Статьи Генератор паролей UUID MD5 Unix-время URL-encode Base64 Форматирование XML Ваш внешний IP Число прописью


Создание zip-архивов

Вернуться назад

28 января 2020

Тэги: Java 10

Если нам нужно упаковать в zip-архив какую-то папку с файлами, то сделать это можно следующим образом:

public static void main(String[] args) throws IOException {
    var fileToZip = new File("/home/devmark/Documents/test-dir");
    try (
            var fos = new FileOutputStream(fileToZip.getAbsolutePath() + ".zip");
            var zipOut = new ZipOutputStream(fos)
    ) {
        zipFile(fileToZip, fileToZip.getName(), zipOut);
    }
}

Тут мы создаём объект File с полным путём до папки. Затем используем конструкцию try-with-resources для создания потоков вывода, которая автоматически закрывает эти потоки при выходе из блока. Мы сначала создаём файловый поток вывода FileOutputStream для записи файла с архивом, затем «обрачиваем» его потоком ZipOutputStream, который как раз и позволяет нам архивировать содержимое. По завершении работы программы zip-архив будет лежать на одном уровне с исходной директорией, называться он будет так же, только с расширением «.zip». Теперь рассмотрим метод zipFile().

private static void zipFile(File fileToZip, String fileName, ZipOutputStream zipOut) throws IOException {
    if (fileToZip.isHidden()) {
        return;
    }
    if (fileToZip.isDirectory()) {
        if (fileName.endsWith("/")) {
            zipOut.putNextEntry(new ZipEntry(fileName));
        } else {
            zipOut.putNextEntry(new ZipEntry(fileName + "/"));
        }
        zipOut.closeEntry();
        var children = fileToZip.listFiles();
        for (File childFile : children) {
            zipFile(childFile, fileName + "/" + childFile.getName(), zipOut);
        }
        return;
    }
    try (var fis = new FileInputStream(fileToZip)) {
        var zipEntry = new ZipEntry(fileName);
        zipOut.putNextEntry(zipEntry);
        var bytes = new byte[1024];
        int length;
        while ((length = fis.read(bytes)) >= 0) {
            zipOut.write(bytes, 0, length);
        }
    }
}

В этом методе мы сначала проверяем текущий файл (или папку), не является она скрытой. Если является, то игнорируем этот файл.

Затем смотрим, не является ли данный файл директорией? Если является, то добавляем её в наш zip-поток с помощью метода putNextEntry(), убедившись, что у неё есть слеш на конце. Поскольку это директория, то в ней могут быть вложены другие директории и папки, поэтому получаем список всех вложенных файлов с помощью метода listFiles() и для каждого из них рекурсивно вызываем этот же метод zipFile().

Если же у нас не папка, а файл, то опять же с помощью try-with-resources открываем входной поток FileInputStream и с помощью буфера в 1024 байт в цикле читаем этот файл и добавляем его к архиву с помощью метода putNextEntry().