JavaでZipファイルの作成というと、クラスの使い方が複雑だとか、日本語ファイルが化けるとかいろいろ面倒な印象でしたが、Apach Commonsのcompressを使うといいみたいです。簡単なコードを書いて、Windows環境で3階層ぐらいのディレクトリを圧縮、解凍してみたら、とりあえず復元できたようなので公開してみます。
公式サイトからリンクされているWikiを参考にしています。
圧縮はcreateZipFile()、解凍はunpackingZipFile()を呼びます。
エラー処理は適当です。
import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.archivers.ArchiveOutputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.commons.compress.utils.IOUtils; public class Zipper { public static void createZipFile(File zipFile, File baseDir) throws ArchiveException, IOException { createZipFile(zipFile, baseDir, null); } public static void createZipFile(File zipFile, File baseDir, String encording) throws ArchiveException, IOException { Zipper zipper = new Zipper(encording); zipper.zip(zipFile, baseDir); } public static void unpackingZipFile(File zipFile, File baseDir) throws ArchiveException, IOException { unpackingZipFile(zipFile, baseDir, null); } public static void unpackingZipFile(File zipFile, File baseDir, String encording) throws ArchiveException, IOException { Zipper zipper = new Zipper(encording); zipper.unzip(zipFile, baseDir); } private String encording = null; public Zipper() { } public Zipper(String encording) { this.encording = encording; } public void zip(File zipFile, File baseDir) throws ArchiveException, IOException { if (zipFile == null) { throw new NullPointerException("zipFile is null"); } if (baseDir == null) { throw new NullPointerException("baseDir is null"); } if (!baseDir.exists()) { throw new NullPointerException("[" + baseDir + "] is nothing"); } OutputStream out = new BufferedOutputStream(new FileOutputStream(zipFile)); ZipArchiveOutputStream archive = new ZipArchiveOutputStream(out); if (encording != null) { archive.setEncoding("Windows-31J"); } String basePath = baseDir.getAbsolutePath(); addAll(archive, basePath, baseDir); archive.finish(); archive.flush(); archive.close(); out.flush(); } private void addAll(ArchiveOutputStream archive, String basePath, File targetFile) throws IOException { if (targetFile.isDirectory()) { File[] children = targetFile.listFiles(); if (children.length == 0) { addDir(archive, basePath, targetFile); } else { for (File file : children) { addAll(archive, basePath, file); } } } else { addFile(archive, basePath, targetFile); } } private void addFile(ArchiveOutputStream archive, String basePath, File file) throws IOException { String path = file.getAbsolutePath(); String name = path.substring(basePath.length()); archive.putArchiveEntry(new ZipArchiveEntry(name)); IOUtils.copy(new FileInputStream(file), archive); archive.closeArchiveEntry(); } private void addDir(ArchiveOutputStream archive, String basePath, File file) throws IOException { String path = file.getAbsolutePath(); String name = path.substring(basePath.length()); archive.putArchiveEntry(new ZipArchiveEntry(name + "/")); archive.closeArchiveEntry(); } public void unzip(File zipFile, File baseDir) throws IOException { if (baseDir == null) { throw new NullPointerException("baseDir is null"); } if (baseDir.exists() && !baseDir.isDirectory()) { throw new NullPointerException("[" + baseDir + "] is not directory"); } baseDir.mkdirs(); String baseDirPath = baseDir.getAbsolutePath(); System.out.println("baseDirPath=" + baseDirPath); final InputStream is = new FileInputStream(zipFile); ZipArchiveInputStream archive; if (encording == null) { archive = new ZipArchiveInputStream(is); } else { archive = new ZipArchiveInputStream(is, encording, true); } ZipArchiveEntry entry; while ((entry = archive.getNextZipEntry()) != null) { File file = new File(baseDirPath + entry.getName()); if (entry.isDirectory()) { file.mkdirs(); } else { if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } OutputStream out = new FileOutputStream(file); IOUtils.copy(archive, out); out.close(); } } archive.close(); } }
ついでなんで簡単なUIも作りました。
import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTabbedPane; import javax.swing.JTextField; import org.apache.commons.compress.archivers.ArchiveException; public class ZipperSwing { public static void main(String[] args) throws ArchiveException, IOException { new ZipperSwing(); } private JFrame frame = new JFrame("Zipper"); private JTextField baseDirForZip = new JTextField(""); private JTextField zipFileNameForZip = new JTextField(""); private JTextField encordForZip = new JTextField("Windows-31J"); private JTextField baseDirForUnzip = new JTextField(""); private JTextField zipFileNameForUnzip = new JTextField(""); private JTextField encordForUnzip = new JTextField("Windows-31J"); private ZipperSwing() { JTabbedPane tab = new JTabbedPane(); tab.add("圧縮", createZipPanel()); tab.add("解凍", createUnzipPanel()); frame.getContentPane().setLayout(new BorderLayout()); frame.getContentPane().add(tab); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(600, 200); frame.setVisible(true); } private JPanel createZipPanel() { JPanel zipPanel = new JPanel(); zipPanel.setLayout(new BorderLayout()); { JPanel panel = new JPanel(); panel.setLayout(new GridLayout(3, 2)); panel.add(new JLabel("圧縮対象のディレクトリまたはフォルダ")); panel.add(zipFileNameForZip); panel.add(new JLabel("作成するZIPファイル名")); panel.add(baseDirForZip); panel.add(new JLabel("ZIPファイルのファイル名のエンコード")); panel.add(encordForZip); zipPanel.add(panel, BorderLayout.CENTER); } JButton execBtn = new JButton("実行"); execBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { zip(); } }); zipPanel.add(execBtn, BorderLayout.SOUTH); return zipPanel; } private JPanel createUnzipPanel() { JPanel zipPanel = new JPanel(); zipPanel.setLayout(new BorderLayout()); { JPanel panel = new JPanel(); panel.setLayout(new GridLayout(3, 2)); panel.add(new JLabel("ZIPファイル")); panel.add(baseDirForUnzip); panel.add(new JLabel("解凍先のディレクトリ")); panel.add(zipFileNameForUnzip); panel.add(new JLabel("ZIPファイルのファイル名のエンコード")); panel.add(encordForUnzip); zipPanel.add(panel, BorderLayout.CENTER); } JButton execBtn = new JButton("実行"); execBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { unzip(); } }); zipPanel.add(execBtn, BorderLayout.SOUTH); return zipPanel; } private void zip() { String baseDir = baseDirForZip.getText(); String zipFileName = zipFileNameForZip.getText(); String encord = encordForZip.getText(); try { Zipper.createZipFile(new File(baseDir), new File(zipFileName), encord); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(frame, e.getMessage(), "err", JOptionPane.WARNING_MESSAGE); return; } JOptionPane.showMessageDialog(frame, "finish"); } private void unzip() { String baseDir = baseDirForUnzip.getText(); String zipFileName = zipFileNameForUnzip.getText(); String encord = encordForUnzip.getText(); try { Zipper.unpackingZipFile(new File(baseDir), new File(zipFileName), encord); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(frame, e.getMessage(), "err", JOptionPane.WARNING_MESSAGE); return; } JOptionPane.showMessageDialog(frame, "finish"); } }