昔Sandboxにあるのを見かけた記憶があるのだけど、今はちゃんとリリース版になっているようだ。他にもzipやgzip、tar、cpioの展開なんかも出来てしまうらしい。
ArchiveStreamFactoryというのを使うと、一見、ファイルの拡張子から形式を自動判別して解凍までさせられるように見えるのだけど、zipやtarのようなArchiveと、gzipやbzip2のようなCompressorは扱いが別になっているので、一元化はしづらそう。
と、細かい話はさておき、試しにZIPを解凍するコードを書いてみた。適当に書いたのだけど、一応動いているっぽい。
// JRE 1.6.0_07
// Commons Compress 1.0
// Commons IO 1.4
// org.apache.commons.compress.archivers.zip.ZipArchiveInputStream
// org.apache.commons.compress.archivers.zip.ZipArchiveEntry
/**
* Commonsのcompressを使ってZipファイルを解凍してみる
*
* @param readPath 読み込むZipファイルのパス
* @param mkdir ディレクトリを生成してその下に解凍する場合は、true
* @throws Exception 例外処理とか余分なコードは略
*/
public void uncompress( String readPath, boolean mkdir )
throws Exception {
// InputStreamの生成
ZipArchiveInputStream arcInputStream = new ZipArchiveInputStream(
new FileInputStream( readPath ) );
// バッファリングしないと処理時間が数十倍になるので、
// BufferedInputStreamでラップ
BufferedInputStream bis = new BufferedInputStream( arcInputStream );
// ディレクトリを生成する場合は、ファイル名から拡張子を除いた名前の
// ディレクトリを生成しておく
String basePath = "./";
if( mkdir ) {
String baseName = FilenameUtils.getBaseName( readPath );
FileUtils.forceMkdir( new File( basePath + baseName ) );
basePath = basePath + baseName + "/";
}
// Entryを1つずつ取得し、ファイル出力していく
ArchiveEntry entry;
while( ( entry = arcInputStream.getNextEntry() ) != null ) {
// ディレクトリの場合は、ディレクトリ生成
if( entry.isDirectory() ) {
FileUtils.forceMkdir(
new File( basePath + entry.getName() ) );
}
// ファイルの場合は、ファイル出力
else {
String writePath = basePath + entry.getName();
// 指定パスのディレクトリが存在しない場合は生成
String dirName = FilenameUtils.getPath( writePath );
FileUtils.forceMkdir( new File( dirName ) );
// OutputStreamの生成
BufferedOutputStream bos = new BufferedOutputStream(
FileUtils.openOutputStream( new File( writePath ) ) );
// 出力
int i = 0;
while( ( i = bis.read() ) != -1 ) {
bos.write( i );
}
// OutputStreamを閉じる
IOUtils.closeQuietly( bos );
}
}
// Streamを閉じる
IOUtils.closeQuietly( bis );
}