JavaでZIPファイルを扱う方法を、初心者にもわかりやすく解説します。
標準ライブラリであるjava.util.zip
を使った基本的な使い方から、階層構造の作成、パスワード付きの圧縮・解凍まで、具体的なコード例を交えて詳しく説明します。さらに、より高度な機能や使いやすさを提供するサードパーティ製のライブラリについても紹介します。
※バージョンはJava8で解説しています。
はじめに

なぜZIP圧縮・解凍が重要なのか?
現代のデジタル世界では、データ量が爆発的に増加しています。画像、動画、テキストなど、様々な形式のデータが日々生成され、保存、転送されています。この膨大なデータを効率的に扱うためには、圧縮 が不可欠です。ZIP圧縮は、データのサイズを縮小することで、ストレージ容量の節約、ネットワーク帯域の削減、データ転送時間の短縮に貢献します。
また、複数のファイルを一つのファイルにまとめるアーカイブ機能も、ZIP形式が広く利用されている理由の一つです。これにより、複数のファイルをまとめて管理したり、バックアップしたりすることが容易になります。
JavaでZIPファイルを扱うメリット
- 豊富なライブラリ: Javaには、標準の
java.util.zip
パッケージをはじめ、Apache Commons Compressなど、強力なZIP処理ライブラリが数多く存在します。 - プラットフォームの独立性: Javaで開発されたZIP処理プログラムは、Windows、macOS、Linuxなど、様々なプラットフォームで実行できます。
- オブジェクト指向: Javaのオブジェクト指向の特性を生かして、ZIPファイルの操作を直感的に行うことができます。
本記事で扱う内容
本記事では、JavaでZIPファイルを扱う方法を、初心者にもわかりやすく解説します。具体的には、以下の内容を扱います。
- Java.util.zipパッケージを使った基本的なZIP圧縮・解凍: 標準のライブラリを使ったシンプルな例から、階層構造の作成まで、段階的に解説します。
- サードパーティ製ライブラリの紹介: より高度な機能や柔軟性を求める場合に便利なライブラリの使い方を説明します。
- パスワード付きのZIP圧縮・解凍: セキュリティが求められる場合に重要な、パスワードを設定したZIPファイルの操作方法について解説します。
これらの内容を通じて、あなたがJavaでZIPファイルの基本的な操作を身に着けることを目指します。
java.util.zipパッケージの基本

圧縮
Javaの標準ライブラリであるjava.util.zip
パッケージには、ZIPファイルの操作に必要なクラスが数多く含まれています。その中でも、ZipOutputStream
クラスは、新しいZIPファイルを作成し、そこにデータを書き込むためのクラスです。
コード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipCompression { public static void main(String[] args) throws IOException { // 圧縮するファイル String sourceFile = "src/main/resources/file.txt"; // 圧縮後のZIPファイル String zipFile = "file.zip"; try (FileOutputStream fos = new FileOutputStream(zipFile); ZipOutputStream zos = new ZipOutputStream(fos)) { // ZipEntryの作成 ZipEntry zipEntry = new ZipEntry("file.txt"); zos.putNextEntry(zipEntry); // ファイルから読み込んでZIPファイルに書き込む try (FileInputStream fis = new FileInputStream(sourceFile)) { byte[] buffer = new byte[1024]; int len; while ((len = fis.read(buffer)) > 0) { zos.write(buffer, 0, len); } } } } } |
解凍
ZipInputStream
クラスは、既存のZIPファイルからデータを抽出するためのクラスです。
コード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; public class ZipDecompress { public static void main(String[] args) throws IOException { // 解凍するZIPファイル String zipFile = "file.zip"; try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) { ZipEntry entry; while ((entry = zis.getNextEntry()) != null) { // ファイルを作成 FileOutputStream fos = new FileOutputStream(entry.getName()); byte[] buffer = new byte[1024]; int len; while ((len = zis.read(buffer)) > 0) { fos.write(buffer, 0, len); } fos.close(); } } } } |
- 上記のコード例は簡略化されており、エラー処理や例外処理は省略されています。実際の開発では、適切なエラー処理を行う必要があります。
ZipEntry
には、圧縮方法やタイムスタンプなどの様々な情報が含まれています。これらの情報を利用することで、より柔軟なZIPファイルの操作が可能になります。
java.util.zipで階層構造のZIPを作成

ディレクトリ構造を作るには?
ZipEntry
クラスのname
プロパティで階層構造になっているファイルのパスとディレクトリ階層を定義します。
ディレクトリとファイルパスの全てを定義しなければならないことと、ディレクトリ階層自体はwrite
メソッドで書き出す必要が無いという点に注意してください。
コード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
import java.io.FileInputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipHierarchy { public static void main(String[] args) throws IOException { String zipFile = "myarchive.zip"; try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(Paths.get(zipFile)))) { // ディレクトリを作成 ZipEntry directoryEntry = new ZipEntry("folder1/"); zos.putNextEntry(directoryEntry); zos.closeEntry(); // ファイル1を追加 ZipEntry fileEntry = new ZipEntry("folder1/file.txt"); zos.putNextEntry(fileEntry); write("src/main/resources/folder1/file.txt", zos); zos.closeEntry(); // ファイル2を追加 ZipEntry anotherFileEntry = new ZipEntry("folder1/another.txt"); zos.putNextEntry(anotherFileEntry); write("src/main/resources/folder1/another.txt", zos); zos.closeEntry(); } } /** * ファイルの書き出し */ public static void write(String filePath, ZipOutputStream zos) { try (FileInputStream fis = new FileInputStream(filePath)) { byte[] buffer = new byte[1024]; int len; while ((len = fis.read(buffer)) != -1) { zos.write(buffer, 0, len); } } catch (IOException e) { throw new RuntimeException(e); } } } |
以下のような形で出力されます。

しかし、なかなか実装が面倒なので、次で階層構造を簡単に圧縮・解凍できるライブラリを紹介します。
階層構造の圧縮・解凍にお薦めのライブラリ

ZT Zip
階層構造化が簡単にできるものとしてzt-zip
があります。ほぼ1行で階層構造の圧縮・解凍ができます。
準備
依存関係を追加します。
ログの実装が必要なのでlogback藻一緒に追加します。
1 2 3 4 5 |
// Gradle implementation group: 'org.zeroturnaround, name: 'zt-zip', version: '1.17' implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.3.15' |
圧縮
圧縮したいルートディレクトリと保存先名を指定するだけで圧縮ができます。(実質1行)
1 2 3 4 5 6 7 8 9 10 11 12 |
import org.zeroturnaround.zip.ZipUtil; import java.io.File; public class ZtZipExample { public static void main(String[] args) { String zipFileName = "myarchive.zip"; String rootDir = "src/main/resources/folder1"; // 圧縮したいルートディレクトリ ZipUtil.pack(new File(rootDir), new File(zipFileName)); } } |
解凍
解凍するZIPファイルと解凍先ディレクトリを指定するだけで簡単に解凍できます。(こちらも実質1行)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import org.zeroturnaround.zip.ZipUtil; import java.io.File; import java.io.IOException; public class ZtZipUnpackExample { public static void main(String[] args) throws IOException { String zipFileName = "myarchive.zip"; String rootDir = "unpack"; // 圧縮したいルートディレクトリ ZipUtil.unpack(new File(zipFileName), new File(rootDir)); } } |
注意点
logbackがJavaのバージョンに依存しているので、若干古い1.3系を使っています。執筆時点では1.5系があるのですが、Java8よりも上のバージョンのため使えません。
こういった依存関係があるので、ご自身のプロジェクトで使用できるかどうかはよくご確認の上、利用を検討してください。
Apache Commons Compress
Apache Commons Compressは、Apacheソフトウェア財団が提供する、Javaで圧縮・解凍処理を行うための強力なライブラリです。ZIP、TAR、GZIP、BZIP2など、様々な圧縮形式に対応しており、Java標準のjava.util.zip
パッケージよりも多くの機能と柔軟性を提供します。
ZT-zipのバージョン依存の問題がJava8では特に発生しなかったので、Java8で最新のライブラリを使いたいという場合はこちらの選択肢になるかと思います。
Apache Commons Compressのメリット
- 豊富な圧縮形式に対応: ZIP、TAR、GZIP、BZIP2など、幅広い圧縮形式をサポートしている。
- 使いやすさ: 直感的なAPIで、簡単に圧縮・解凍処理を実装できる。
- 階層構造に関してはZT-zipには劣りますが、再帰処理を使うことで実装できるのでそれほど難しくはありません。
基本的な使い方
階層構造のあるアーカイバをZIP圧縮するコード例です。
ディレクトリのルートを指定すると再帰的にすべてのディレクトリとファイルを圧縮できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; public class ZipApacheExample { public static void main(String[] args) throws IOException { String zipFileName = "myarchive.zip"; String rootDir = "src/main/resources/folder1"; // 圧縮したいルートディレクトリ try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(Files.newOutputStream(Paths.get(zipFileName)))) { File root = new File(rootDir); addDirectoryToZip(zos, root, ""); } } private static void addDirectoryToZip(ZipArchiveOutputStream zos, File file, String parent) throws IOException { String zipEntryName = parent + file.getName(); ZipArchiveEntry zipEntry = new ZipArchiveEntry(zipEntryName); zos.putArchiveEntry(zipEntry); if (file.isDirectory()) { // ディレクトリの場合、中身のファイルやディレクトリを再帰的に追加 File[] files = file.listFiles(); if (files != null) { for (File childFile : files) { addDirectoryToZip(zos, childFile, zipEntryName + "/"); } } } else { // ファイルの場合、ファイルの内容をZIPファイルに書き込む try (FileInputStream fis = new FileInputStream(file)) { byte[] buffer = new byte[1024]; int len; while ((len = fis.read(buffer)) > 0) { zos.write(buffer, 0, len); } } } zos.closeArchiveEntry(); } } |
パスワード付き圧縮・解凍のお薦めライブラリ

zip4j
java.util.zip
Zt zip
Apache Commons Compress
ではパスワードZIPはサポートされていません。そのため、別のライブラリを検討する必要があります。
パスワード付ZIPとして、おそらく最もよく使われているのがzip4j
です。
コード例
依存関係の追加
1 2 3 4 |
// Gradle implementation group: 'net.lingala.zip4j', name: 'zip4j', version: '2.11.5' |
圧縮
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import net.lingala.zip4j.ZipFile; import net.lingala.zip4j.model.ZipParameters; import net.lingala.zip4j.model.enums.CompressionLevel; import net.lingala.zip4j.model.enums.EncryptionMethod; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class PasswordZip { public static void main(String[] args) throws IOException { ZipParameters zipParameters = new ZipParameters(); zipParameters.setEncryptFiles(true); zipParameters.setCompressionLevel(CompressionLevel.HIGHER); zipParameters.setEncryptionMethod(EncryptionMethod.AES); try (ZipFile zipFile = new ZipFile("myarchive.zip", "password".toCharArray())) { List<File> files = new ArrayList<File>(){{ add(new File("src/main/resources/folder1/file.txt")); add(new File("src/main/resources/folder1/another.txt")); }}; zipFile.addFiles(files, zipParameters); } } } |
階層構造を直接サポートするAPIは用意されていないので、対象になるファイルを個別に指定する必要があります。
解凍
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import net.lingala.zip4j.ZipFile; import java.io.IOException; public class PasswordUnZip { public static void main(String[] args) throws IOException { String outputPath = "outputDir"; try (ZipFile zipFile = new ZipFile("myarchive.zip", "password".toCharArray())) { zipFile.extractAll(outputPath); } } } |
解凍時は階層構造を意識する必要はありません。
まとめ
- 圧縮・解凍には、java.util.zip, zt-zip, Apache common Compresse, zip4jという選択肢がある。
- 各々をまとめると以下の通り。
ライブラリ | 階層構造 | パスワード付 |
---|---|---|
java.util.zip | ||
zt-zip | ||
Apache common Compresse | ||
zip4j |
コメント