今回はJavaでZipファイルを解凍する処理を書く方法を紹介します。
ファイル圧縮と同様にJavaの標準クラスを使うことで、実装することが出来ます。
ファイル圧縮については以下の記事を参照ください。
ファイルの解凍は1つのメソッドで実装してもいいのですが、今回はメソッドを2つ用意することで、解凍する処理と、解凍時にファイルに出力する処理を分け、ソースを分かりやすくしています。
解凍処理は圧縮処理に比べると複雑になりますが、決して難しいものではありません。
しっかりとソースを読めば理解が出来るレベルなので、何とか付いて来て欲しいと思います。
なお、今回もJavaの標準プロジェクトを用いてmainメソッドから呼び出すことで、ファイルの解凍を行います。
必要なパッケージのインポート
Javaを用いて解凍処理を実装する場合必要な標準クラスライブラリのインポートは以下のようになります。
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
最初のクラスライブラリは、解凍時のファイル作成の時にファイルにデータを書き込むのに使っています。
残りは、ファイル操作のライブラリとZipファイル操作のライブラリとなります。
Zipファイルの解凍を実装するメソッドの定義
では、早速Zipファイルを解凍するメソッドを定義していきたいと思います。
JavaでファイルのZipファイルの解凍処理を実現するために、以下の2つのメソッドを記述します。
まずはファイルを解凍する一連の処理を定義するメソッドです。
//ファイルを解凍する
public static void extractZip() {
File outPutDir = new File("./");
//解凍先のディレクトリがない場合はディレクトリを作成する
if(!outPutDir.exists()) {
outPutDir.mkdir();
}
try(ZipInputStream zis = new ZipInputStream(new FileInputStream("C:\\temp\\archive.zip"))){
//ZIPファイル中に含まれるファイルを解凍する
ZipEntry ze = zis.getNextEntry();
while(ze != null) {
//ファイルの解凍先パスとファイル名(圧縮ファイルと同じ場所にフォルダを作成して解凍する)
String path = "C:\\temp\\archive" + File.separator + ze.getName();
//解凍先のフォルダを作成する
File dr = new File("C:\\temp\\archive");
dr.mkdir();
if(!ze.isDirectory()) {
//ファイルの場合はファイルを解凍
extractFile(zis, path);
} else {
//ディレクトリの場合はディレクトリを作成
File dir = new File(path);
dir.mkdirs();
}
//解凍処理が終わったら一旦入力ストリームをクローズ
zis.closeEntry();
//次のファイルがあれば取得する
ze = zis.getNextEntry();
}
}
catch(Exception e) {
e.printStackTrace();
}
return;
}
このメソッドでやっていることは、Zipファイルを読み込んで、ファイルの中身を確認します。
途中で、以下のようにファイルを解凍する時に、Zipファイルと同じファイル名のフォルダを作成する処理が入っていますが、これを書かなくても解凍自体は出来ます。
//解凍先のフォルダを作成する
File dr = new File("C:\\temp\\archive");
dr.mkdir();
ただ、このフォルダを作成する処理がないとZipファイルを置いたフォルダにフォルダを作らずに解凍してファイルが出来てしまうので、既に他のファイルが置いてある場合は、どのファイルが解凍により生成されたファイルなのかが一目見て分からないため、不便になります。
ファイルの中身の数だけファイルを解凍して圧縮前のファイルを出力する処理を行うことになりますが、ファイルに出力する処理そのものは以下のメソッドで定義しています。
//ファイルの解凍処理
private static void extractFile(ZipInputStream zis, String path) {
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path))){
//一定のバイトずつ出力していく
byte[] bytesIn = new byte[256];
int read = 0;
while((read = zis.read(bytesIn)) != -1) {
bos.write(bytesIn, 0, read);
}
}
catch(Exception e) {
e.printStackTrace();
}
}
ここでは256バイトずつ書き出していますが、必ずしも256バイトである必要はなく、1024、4096などのバイト長の配列を使っても問題なく解凍が出来ます。
今回のコードはC:¥tempに圧縮ファイルがあることを前提で、圧縮ファイルの解凍処理を行っています。
圧縮ファイルのある場所とファイル解凍先を別々にすることも可能で、ソース上でべた書きしてある箇所を変更すると、圧縮ファイルのある場所ではなく、特定のフォルダに解凍するように変更が可能です。
特定のフォルダに解凍することは、解凍したファイルを一時ファイルとして利用し、システムに取り込むなどの応用が出来ますので、覚えておいて損はないでしょう。
実際の動作
では、実際に動作を確認してみましょう。
まず、前準備としてC:\tempに圧縮ファイルを置きます。
この状態で、先ほど書いた処理をmainメソッドから呼び出して実行してみます。
すると、C:¥tempにフォルダが作成されました。
このフォルダを開くと、圧縮されていたファイルが解凍できている状態が確認できました。
まとめ
今回は以下のことをお話ししました。
- JavaでZipファイルの解凍を行う場合は標準クラスのインポートをすると実現できること
- Zipファイルを解凍したファイルの出力はバッフア出力ストリームに書き出すことで実現できること
- Zipファイルの解凍はプロジェクトフォルダの直下のファイルではなく、任意のフォルダのZipファイルを解凍することが出来ること
- Zipファイルの解凍の際にフォルダを作成してその中に解凍したファイルを入れることも可能であること
ファイルの解凍は実際の業務でも応用しなければいけないことがあるかと思います。
たとえば、一時フォルダファイルにZipファイルを解凍して、解凍したファイルをシステムに連携した後、Zipファイルは履歴として履歴用のフォルダに移動する、解凍したファイルは不要になったので削除するなどのことが、実際のシステム開発では実装する必要があるケースが想定されます。
Zipファイルを解凍する処理はZipファイルに圧縮する処理よりも少し複雑になりますが、今回掲載したサンプルコードを見て理解すればしっかりと応用できるはずです。
今回はパスワード付ではないZipファイルを解凍する処理を紹介しましたが、パスワード付Zipファイルを解凍して、システムに連携する必要があることも想定されます。
パスワード付Zipファイルの解凍については調査のうえ、別記事にしてまとめたいと思います。
今回の記事はここまでとなります。
また次の記事でお会いしましょう。