- Home »

Пример распаковки файлов в Java
Сегодня разберёмся с одной из тех задач, которые вроде бы просты, но на практике часто вызывают вопросы: как распаковать архив (zip, tar, rar и т.д.) средствами Java? Почему это важно? Потому что автоматизация развёртывания, обновления, резервного копирования и прочих серверных рутин — это не только про bash-скрипты и ansible, но и про интеграцию с приложениями, где Java — частый гость. Если вы когда-нибудь писали свой deployer, автосборщик, или просто хотели автоматизировать развертывание WAR-файлов, то наверняка сталкивались с задачей распаковки архивов. В этой статье — не только базовые примеры, но и реальные кейсы, подводные камни, сравнения с альтернативами и советы, которые сэкономят вам кучу времени.
Как это работает? — Архивы и Java: что под капотом
В Java есть встроенная поддержка работы с архивами, но она ограничена zip-форматом (и, как ни странно, jar — это тоже zip). Для других форматов (tar, rar, 7z) придётся подключать сторонние библиотеки. В стандартной библиотеке (java.util.zip) есть классы ZipInputStream
, ZipFile
, ZipEntry
— с их помощью можно читать, создавать и распаковывать zip-архивы. Для tar, gzip, bzip2 и прочих — используем Apache Commons Compress или junrar для rar.
- Zip — поддерживается из коробки.
- Tar, Gzip, Bzip2 — Apache Commons Compress (официальный сайт).
- Rar — junrar (github).
- 7z — SevenZipJBinding (github), но тут уже сложнее.
Всё это позволяет не только распаковывать архивы, но и интегрировать этот процесс в ваши приложения, автоматизировать деплой, обновления, миграции данных и прочие серверные задачи.
Как быстро и просто всё настроить?
Рассмотрим два сценария:
- 1. Нужно просто распаковать zip-архив средствами Java (например, для автодеплоя на сервере).
- 2. Требуется поддержка других форматов (tar, rar, 7z).
1. Распаковка zip-архива стандартными средствами Java
Всё, что нужно — JDK 8+ (лучше 11+), никаких дополнительных зависимостей. Вот пример кода:
import java.io.*;
import java.nio.file.*;
import java.util.zip.*;
public class Unzipper {
public static void unzip(String zipFilePath, String destDir) throws IOException {
File dir = new File(destDir);
if (!dir.exists()) dir.mkdirs();
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFilePath))) {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
File newFile = new File(destDir, entry.getName());
if (entry.isDirectory()) {
newFile.mkdirs();
} else {
new File(newFile.getParent()).mkdirs();
try (FileOutputStream fos = new FileOutputStream(newFile)) {
byte[] buffer = new byte[4096];
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
}
}
zis.closeEntry();
}
}
}
}
Вызов:
Unzipper.unzip("/path/to/archive.zip", "/path/to/destination/");
Плюсы: просто, работает везде, не требует зависимостей.
Минусы: только zip, нет поддержки rar/tar/7z, нет прогресса, нет защиты от path traversal (см. ниже!).
2. Распаковка других форматов — Apache Commons Compress
Добавьте зависимость в ваш pom.xml
(если используете Maven):
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.26.1</version>
</dependency>
Пример для tar.gz:
import org.apache.commons.compress.archivers.tar.*;
import org.apache.commons.compress.compressors.gzip.*;
public static void untarGz(String tarGzPath, String destDir) throws IOException {
try (TarArchiveInputStream tis = new TarArchiveInputStream(
new GzipCompressorInputStream(new FileInputStream(tarGzPath)))) {
TarArchiveEntry entry;
while ((entry = tis.getNextTarEntry()) != null) {
File newFile = new File(destDir, entry.getName());
if (entry.isDirectory()) {
newFile.mkdirs();
} else {
new File(newFile.getParent()).mkdirs();
try (FileOutputStream fos = new FileOutputStream(newFile)) {
byte[] buffer = new byte[4096];
int len;
while ((len = tis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
}
}
}
}
}
Для rar — используйте junrar, для 7z — SevenZipJBinding (но там придётся повозиться с нативными библиотеками).
Примеры, схемы, практические советы
Вот несколько реальных кейсов, с которыми сталкивался лично или видел на stackoverflow/habr:
- Кейс 1: Автоматизация деплоя на сервере
Нужно развернуть свежий билд приложения (zip-архив) на сервере после CI/CD. Решение — скрипт на Java, который скачивает архив, распаковывает в нужную директорию, перезапускает сервис. Всё просто, если архив zip. Если tar.gz — используем Apache Commons Compress. - Кейс 2: Распаковка пользовательских архивов
Пользователь загружает архив с файлами (например, для импорта данных). Тут важно: архив может быть с сюрпризами (path traversal, вложенные архивы, нестандартные имена файлов). Рекомендация — всегда проверяйте, что путь распаковываемого файла не выходит за пределы целевой директории:
File destFile = new File(destDir, entry.getName());
String destPath = destFile.getCanonicalPath();
if (!destPath.startsWith(new File(destDir).getCanonicalPath() + File.separator)) {
throw new IOException("Entry is outside of the target dir: " + entry.getName());
}
Это защитит от атак типа../../etc/passwd
. - Кейс 3: Распаковка больших архивов
Если архив огромный (гигабайты), лучше использовать стриминговую распаковку (ZipInputStream, TarArchiveInputStream), чтобы не держать всё в памяти. Для прогресса — можно считать количество обработанных байт и выводить в лог.
Таблица сравнения: стандартные средства vs сторонние библиотеки
Решение | Форматы | Зависимости | Платформенность | Особенности |
---|---|---|---|---|
java.util.zip | zip, jar | нет | любая | Встроено в JDK, просто, но только zip |
Apache Commons Compress | zip, tar, gzip, bzip2, ar, cpio, xz, 7z (ограниченно) | да | любая | Гибко, поддержка многих форматов, активно развивается |
junrar | rar | да | любая | Только rar, не всегда поддерживает rar5 |
SevenZipJBinding | 7z, zip, rar, tar, gzip, bzip2 | да (и нативные библиотеки) | ограничено (нужен native) | Мощно, но сложнее в настройке, нужен native |
Похожие решения, программы и утилиты
- unzip, tar, 7z — классика для Linux. Можно вызывать из Java через
ProcessBuilder
, если не хочется возиться с библиотеками. - Ant — в Ant есть задачи
<unzip>
,<untar>
и т.д. Можно использовать через Ant API. - Spring Boot DevTools — умеет автоматически распаковывать jar/war при hot reload, но это уже специфично.
Если задача — просто распаковать архив на сервере, проще всего использовать стандартные утилиты ОС. Но если нужно интегрировать распаковку в Java-приложение (например, для автоматизации деплоя, миграций, обработки пользовательских архивов) — лучше использовать Java-библиотеки.
Статистика, сравнение с другими решениями
- По данным Maven Central, Apache Commons Compress — одна из самых популярных библиотек для работы с архивами в Java (более 100 млн загрузок).
- Стандартный
java.util.zip
используется в большинстве Java-проектов, но только для zip/jar. - junrar и SevenZipJBinding — нишевые решения, но незаменимы, если нужно работать с rar/7z.
- В крупных проектах (например, Jenkins, Nexus, Artifactory) для работы с архивами часто используют именно Apache Commons Compress.
Интересные факты и нестандартные способы использования
- Можно распаковывать архивы “на лету” из потока (например, скачивать архив по HTTP и сразу распаковывать, не сохраняя на диск).
- Некоторые архивы (особенно rar, 7z) могут содержать вложенные архивы — для их обработки потребуется рекурсивная распаковка.
- В Java можно создавать самораспаковывающиеся jar-файлы (fat jar), которые при запуске сами себя распаковывают и запускают нужный класс.
- Для защиты от path traversal атак всегда проверяйте canonical path (см. выше).
- Можно использовать распаковку архивов для автоматизации обновления конфигураций, миграций, резервного копирования (например, nightly-архивы с логами, которые потом автоматически распаковываются и анализируются).
Какие новые возможности открываются и чем это поможет в автоматизации и скриптах?
- Интеграция распаковки архивов в ваши Java-приложения позволяет автоматизировать деплой, обновления, миграции данных без внешних скриптов.
- Можно реализовать “горячее” обновление приложения: скачали новый билд, распаковали, перезапустили сервис — всё из одного Java-процесса.
- Обработка пользовательских архивов (например, импорт данных, загрузка плагинов) становится безопаснее и проще.
- Можно строить сложные пайплайны обработки данных: скачали архив → распаковали → обработали файлы → удалили временные данные.
- Возможность работы с архивами “на лету” (streaming) экономит место на диске и ускоряет обработку больших данных.
Вывод — заключение и рекомендации
Распаковка архивов в Java — задача, с которой сталкивается каждый, кто автоматизирует серверные процессы, деплой, обновления или просто интегрирует работу с файлами в свои приложения. Если вам нужен быстрый и надёжный способ распаковать zip-архив — используйте стандартный java.util.zip
. Для других форматов (tar, gzip, bzip2, rar, 7z) — подключайте Apache Commons Compress или специализированные библиотеки (junrar, SevenZipJBinding). Не забывайте про безопасность: всегда проверяйте пути файлов, чтобы избежать path traversal атак.
Если вы ищете хостинг для своих Java-приложений — обратите внимание на VPS или выделенные серверы — это даст вам полный контроль над окружением и возможностью автоматизировать любые задачи, включая распаковку архивов средствами Java.
Встраивайте распаковку архивов в свои пайплайны, автоматизируйте деплой, делайте резервные копии, обрабатывайте пользовательские данные — всё это реально и удобно с помощью Java. А если хочется ещё больше автоматизации — комбинируйте Java с bash-скриптами, ansible, docker и CI/CD. Главное — не бойтесь экспериментировать и автоматизировать рутину!
Официальные ресурсы для самостоятельного изучения:
Если остались вопросы — смело спрашивайте в комментариях, делитесь своими кейсами и лайфхаками. Happy hacking!
В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.
Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.