Статьи
YouTube-канал

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

27 января 2020

Тэги: Java 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().


Облако тэгов

Kotlin, Java, Java 16, Java 11, Java 10, Java 9, Java 8, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Hibernate, Collections, Stream API, многопоточность, ввод-вывод, Apache, maven, gradle, JUnit, YouTube, новости, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml

Последние статьи


Комментарии

Добавить комментарий

×

devmark.ru