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


Распаковка zip-архивов

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

29 января 2020

Тэги: Java 10

Ранее мы рассматривали Создание zip-архивов, а теперь попробуем выполнить обратную операцию. Если у нас имеется zip-архив с файлами, то распаковать его мы можем следующим образом:

public static void main(String[] args) throws IOException {
    try (var file = new ZipFile("/home/devmark/Documents/test.zip")) {
        var entries = file.entries();
        var uncompressedDirectory = new File(file.getName()).getParent() + File.separator;
        while (entries.hasMoreElements()) {
            var entry = entries.nextElement();
            if (entry.isDirectory()) {
                processDirectory(uncompressedDirectory, entry);
            } else {
                processFile(file, uncompressedDirectory, entry);
            }
        }
    }
}

Мы создаём объект ZipFile из пакета java.util, в конструктор которому передаём полный путь до нашего архива. Все действия выполняем в конструкции try-with-resources, которая автоматически закроет ресурс, связанный с нашим архивом, в конце работы с ним.

Метод entries() предоставляет список содержащихся в архиве сущностей (файлов и папок). Затем мы можем обходить эти сущности при помощи цикла while и метода hasMoreElements(). Распакованный архив будем складывать в ту же директорию, где лежит исходный файл с архивом.

В цикле мы проверяем у каждой сущности признак isDirectory() и в зависимости от этого либо создаём подпапки в папке назначения, либо распаковываем содержащийся в архиве файл. Ниже приведены оба метода: processDirectory() и processFile().

Обработка директории

private static void processDirectory(String uncompressedDirectory, ZipEntry entry) {
    var newDirectory = uncompressedDirectory + entry.getName();
    System.out.println("Creating Directory: " + newDirectory);
    var directory = new File(newDirectory);
    if (!directory.exists()) {
        directory.mkdirs();
    }
}

Тут мы прибавляем к нашему базовому пути имя папки, содержащейся в архиве. Затем создаём объект File, асоциированный с этой новой папкой и проверяем её существование. Если её нет (что вполне ожидаемо), то создаем все папки с подпапками, содержащиеся в данном пути с помощью метода mkdirs().

Обработка файла

private static void processFile(ZipFile file, String uncompressedDirectory, ZipEntry entry) throws IOException {
    try (
            var is = file.getInputStream(entry);
            var bis = new BufferedInputStream(is)
    ) {
        var uncompressedFileName = uncompressedDirectory + entry.getName();
        try (
                var os = new FileOutputStream(uncompressedFileName);
                var bos = new BufferedOutputStream(os)
        ) {
            while (bis.available() > 0) {
                bos.write(bis.read());
            }
        }
    }
    System.out.println("Written: " + entry.getName());
}

В конструкции try-with-resources мы создаём поток InputStream, связанный с упакованным файлом внутри архива. Затем оборачиваем его буферизованным потоком BufferedInputStream, который минимизирует количество операций с файловой системой, что заметно ускоряет процесс распаковки.

Затем создаём аналогично поток FileOutputStream связанный с файлом, который мы собираемся записать. Оборачиваем его также в BufferedOutputStream для ускорения и в цикле пишем распакованный файл с помощью метода write().