Java ZIP圧縮する方法 ディレクトリ指定やファイル指定 - ZipEntry・ZipOutputStream

JavaでZipEntryとZipOutputStreamを使ってZIPアーカイブする方法です。

ZipOutputStream クラスは、java.util.zip.ZipOutputStream, org.apache.tools.zip.ZipOutputStream の2種類がありますが、日本語ファイル名を扱える org.apache.tools.zip.ZipOutputStream を利用しましょう。

実務では、ZIP 圧縮したい方法として「特定のディレクトリを圧縮したい」「特定のファイルだけ圧縮したい」などの要望があるかと思います。今回はその両方を実現するためのサンプルを用意しました。

ここでは JavaでZipEntryとZipOutputStreamを使ってZIPアーカイブする方法 を紹介します。


サンプルソース

それでは、実際のソースを見ながら解説してきます。

今回は、ZipCompressUtils というクラスを用意しました

package com.en.saka.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;

/**
 * ZipCompressUtils は、ZIP 圧縮をおこなう上で利便性の高い機能を提供します。
 *
 * @author saka-en.
 * @version $Revision: 1.0 $ $Date: 2013.10.24 $ $Description: 新規作成 $
 */
public class ZipCompressUtils {

  /**
   * 指定されたディレクトリ内のファイルを ZIP アーカイブし、指定されたパスに作成します。
   * デフォルト文字コードは Shift_JIS ですので、日本語ファイル名も対応できます。
   *
   * @param fullPath 圧縮後の出力ファイル名をフルパスで指定 ( 例: C:/sample.zip )
   * @param directory 圧縮するディレクトリ ( 例; C:/sample )
   * @return 処理結果 true:圧縮成功 false:圧縮失敗
   */
  public static boolean compressDirectory( String filePath, String directory ) {
    File baseFile = new File(filePath);
    File file = new File(directory);
    ZipOutputStream outZip = null;
    try {
      // ZIPファイル出力オブジェクト作成
      outZip = new ZipOutputStream(new FileOutputStream(baseFile));
      archive(outZip, baseFile, file);
    } catch ( Exception e ) {
      // ZIP圧縮失敗
      return false;
    } finally {
      // ZIPエントリクローズ
      if ( outZip != null ) {
        try { outZip.closeEntry(); } catch (Exception e) {}
        try { outZip.flush(); } catch (Exception e) {}
        try { outZip.close(); } catch (Exception e) {}
      }
    }
    return true;
  }

  /**
   * 指定された ArrayList のファイルを ZIP アーカイブし、指定されたパスに作成します。
   * デフォルト文字コードは Shift_JIS ですので、日本語ファイル名も対応できます。
   *
   * @param filePath 圧縮後のファイル名をフルパスで指定 ( 例: C:/sample.zip )
   * @param fileList 圧縮するファイルリスト  ( 例; {C:/sample1.txt, C:/sample2.txt} )
   * @return 処理結果 true:圧縮成功 false:圧縮失敗
   */
  public static boolean compressFileList( String filePath, ArrayList<String> fileList ) {

    ZipOutputStream outZip = null;
    File baseFile = new File(filePath);
    try {
      // ZIPファイル出力オブジェクト作成
      outZip = new ZipOutputStream(new FileOutputStream(baseFile));
      // 圧縮ファイルリストのファイルを連続圧縮
      for ( int i = 0 ; i < fileList.size() ; i++ ) {
        // ファイルオブジェクト作成
        File file = new File((String)fileList.get(i));
        archive(outZip, baseFile, file, file.getName(), "Shift_JIS");
      }
    } catch ( Exception e ) {
      // ZIP圧縮失敗
      return false;
    } finally {
      // ZIPエントリクローズ
      if ( outZip != null ) {
        try { outZip.closeEntry(); } catch (Exception e) {}
        try { outZip.flush(); } catch (Exception e) {}
        try { outZip.close(); } catch (Exception e) {}
      }
    }
    return true;
  }

  /**
   * ディレクトリ圧縮のための再帰処理
   *
   * @param outZip ZipOutputStream
   * @param baseFile File 保存先ファイル
   * @param file File 圧縮したいファイル
   */
  private static void archive(ZipOutputStream outZip, File baseFile, File targetFile) {
    if ( targetFile.isDirectory() ) {
      File[] files = targetFile.listFiles();
      for (File f : files) {
        if ( f.isDirectory() ) {
          archive(outZip, baseFile, f);
        } else {
          if ( !f.getAbsoluteFile().equals(baseFile)  ) {
            // 圧縮処理
            archive(outZip, baseFile, f, f.getAbsolutePath().replace(baseFile.getParent(), "").substring(1), "Shift_JIS");
          }
        }
      }
    }
  }

  /**
   * 圧縮処理
   *
   * @param outZip ZipOutputStream
   * @param baseFile File 保存先ファイル
   * @param targetFile File 圧縮したいファイル
   * @parma entryName 保存ファイル名
   * @param enc 文字コード
   */
  private static boolean archive(ZipOutputStream outZip, File baseFile, File targetFile, String entryName, String enc) {
    // 圧縮レベル設定
    outZip.setLevel(5);

    // 文字コードを指定
    outZip.setEncoding(enc);
    try {

      // ZIPエントリ作成
      outZip.putNextEntry(new ZipEntry(entryName));

      // 圧縮ファイル読み込みストリーム取得
      BufferedInputStream in = new BufferedInputStream(new FileInputStream(targetFile));

      // 圧縮ファイルをZIPファイルに出力
      int readSize = 0;
      byte buffer[] = new byte[1024]; // 読み込みバッファ
      while ((readSize = in.read(buffer, 0, buffer.length)) != -1) {
        outZip.write(buffer, 0, readSize);
      }
      // クローズ処理
      in.close();
      // ZIPエントリクローズ
      outZip.closeEntry();
    } catch ( Exception e ) {
      // ZIP圧縮失敗
      return false;
    }
    return true;
  }
}

compressDirectory メソッド

指定したディレクトリを圧縮したい場合に利用します。

引数説明
filePathStringZIP ファイルの保存先を指定します。
( 例: C:/サンプル.zip )
directoryString圧縮したいディレクトリを指定します。
( 例; C:/samples )

それでは、テストしてみましょう。

今回は、[ C:/samples/サンプルtxt.zip ] というファイル名で、[ C:/samples/txt ] のディレクトリを圧縮してみます。

ZIP Compress 001

以下のテストソースを実行します。

ZipCompressUtils.compressDirectory("C:/samples/サンプルtxt.zip", "C:/samples/txt");

結果は、以下の通りです。

ZIP Compress 002

ZIP Compress 003

ふむ、いい感じ。

compressFileList メソッド

指定したファイルだけを圧縮したい場合に利用します。

引数説明
filePathStringZIP ファイルの保存先を指定します。
( 例: C:/サンプル.zip )
fileListArrayList<String>圧縮したいファイルリストを指定します。
( 例; {C:/sample1.txt, C:/sample2.txt} )

それでは、テストしてみましょう。

今回は、[ C:/samples/サンプルtxt.zip ] というファイル名で、[ C:/samples/txt/salmpe1.txt, C:/samples/txt/salmpe3.txt} ] のファイルを圧縮してみます。

以下のテストソースを実行します。

ArrayList<String> fileList = new ArrayList<String>();
fileList.add("C:/samples/txt/salmpe1.txt");
fileList.add("C:/samples/txt/salmpe3.txt");
ZipCompressUtils.compressFileList("C:/samples/サンプルtxt.zip", fileList);

結果は、以下の通りです。

ZIP Compress 004

ZIP Compress 005

ふむふむ、いい感じ。

ZIP 解凍する方法

おつかれさまでした。

この記事がお役に立ちましたら シェア をお願いいたします。