package com.revolsys.io; 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 java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; import com.revolsys.spring.resource.Resource; public class ZipUtil { /** * Add the all the sub directories and files below the directory to the zip * output stream. The names of the files in the ZIP file will be relative to * the directory. * * @param zipOut The zip output stream to add the files to. * @param directory The directory containing the files. * @throws IOException * @throws IOException If an I/O error occurs. */ public static void addDirectoryToZipFile(final ZipOutputStream zipOut, final File directory) throws IOException { addDirectoryToZipFile(zipOut, directory, directory); } /** * Add the all the sub directories and files below the directory to the zip * output stream. The names of the files in the ZIP file will be relative to * the baseDirectory. * * @param zipOut The zip output stream to add the files to. * @param baseDirectory The base directory files are relative to. * @param directory The directory containing the files. * @throws IOException If an I/O error occurs. */ public static void addDirectoryToZipFile(final ZipOutputStream zipOut, final File baseDirectory, final File directory) throws IOException { final File[] files = directory.listFiles(); if (files != null) { for (final File file : files) { if (file.isDirectory()) { addDirectoryToZipFile(zipOut, baseDirectory, file); } else { final String zipEntryName = FileUtil.getRelativePath(baseDirectory, file); zipOut.putNextEntry(new ZipEntry(zipEntryName)); final InputStream in = new FileInputStream(file); FileUtil.copy(in, zipOut); in.close(); } } } } /** * Add the list of file names to the zip output stream. The names of the files * in the ZIP file will be relative to the baseDirectory. * * @param zipOut The zip output stream to add the files to. * @param baseDirectory The base directory files are relative to. * @param fileNames The list of file names to add. * @throws IOException If an I/O error occurs. */ public static void addFilesToZipFile(final ZipOutputStream zipOut, final File baseDirectory, final String[] fileNames) throws IOException { for (final String fileName : fileNames) { final File file = new File(baseDirectory, fileName); if (file.isDirectory()) { addDirectoryToZipFile(zipOut, baseDirectory, file); } else { zipOut.putNextEntry(new ZipEntry(fileName)); final InputStream in = new FileInputStream(file); FileUtil.copy(in, zipOut); in.close(); } } } public static List<String> unzipFile(final File file, final File outputDirectory) throws IOException { final List<String> entryNames = new ArrayList<>(); final ZipFile zipFile = new ZipFile(file); for (final Enumeration<? extends ZipEntry> entries = zipFile.entries(); entries .hasMoreElements();) { final ZipEntry entry = entries.nextElement(); final String entryName = entry.getName(); final File outputFile = new File(outputDirectory, entryName); outputFile.getParentFile().mkdirs(); FileUtil.copy(zipFile.getInputStream(entry), outputFile, entry.getSize()); entryNames.add(entryName); } zipFile.close(); return entryNames; } public static File unzipFile(final Resource resource) throws IOException { String filename = resource.getFilename(); while (filename.length() < 3) { filename += "x"; } final File directory = FileUtil.newTempDirectory(filename, ".zip"); final InputStream in = resource.getInputStream(); final ZipInputStream zipIn = new ZipInputStream(in); try { ZipEntry entry; while ((entry = zipIn.getNextEntry()) != null) { final String entryName = entry.getName(); final File outputFile = new File(directory, entryName); outputFile.getParentFile().mkdirs(); if (entry.isDirectory()) { outputFile.mkdir(); } else { FileUtil.copy(zipIn, outputFile); } zipIn.closeEntry(); } FileUtil.closeSilent(zipIn); return directory; } catch (final IOException e) { FileUtil.closeSilent(zipIn); FileUtil.deleteDirectory(directory); throw e; } } public static void zipDirectory(final File zipFile, final File directory) { try { final OutputStream outputStream = new FileOutputStream(zipFile); zipDirectory(directory, outputStream); } catch (final IOException e) { throw new RuntimeException("Unable to create zip file:" + zipFile, e); } } public static void zipDirectory(final File directory, final OutputStream outputStream) throws IOException { final ZipOutputStream zipOut = new ZipOutputStream(outputStream); addDirectoryToZipFile(zipOut, directory, directory); zipOut.close(); } }