package com.twasyl.slideshowfx.utils; import com.twasyl.slideshowfx.utils.io.ListFilesFileVisitor; import java.io.*; import java.nio.file.Files; import java.util.List; import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; /** * This class provides utility methods for working with Zip files. * * @author Thierry Wasylczenko */ public class ZipUtils { private static final Logger LOGGER = Logger.getLogger(ZipUtils.class.getName()); /** * Unzpi the given archive into the provided destination. If the destination does not exist it is created. * @param archive The archive file to unzip. * @param destination The destination directory where the archive will be unzipped. * @throws IOException If the archive file does not exist. * @throws java.lang.NullPointerException If the archive file or the destination is null. */ public static void unzip(File archive, File destination) throws IOException, IllegalArgumentException { if(archive == null) throw new NullPointerException("The ZIP file can not be null"); if(!archive.exists()) throw new FileNotFoundException("The ZIP file does not exist"); // Unzip LOGGER.fine("Extracting file " + archive.toURI().toASCIIString()); final FileInputStream inputStream = new FileInputStream(archive); unzip(inputStream, destination); } /** * Unzpi the given archive into the provided destination. If the destination does not exist it is created. * @param archive The archive file to unzip. * @param destination The destination directory where the archive will be unzipped. * @throws IOException If the archive file does not exist. * @throws java.lang.NullPointerException If the archive file or the destination is null. */ public static void unzip(InputStream archive, File destination) throws IOException, IllegalArgumentException { if(archive == null) throw new NullPointerException("The ZIP file can not be null"); if(destination == null) throw new NullPointerException("The destination can not be null"); if(!destination.exists()) { if(!destination.mkdirs()) { throw new IOException("Can not create destination folder"); } } ZipInputStream zipReader = new ZipInputStream(archive); ZipEntry zipEntry; File extractedFile; while((zipEntry = zipReader.getNextEntry()) != null) { extractedFile = new File(destination, zipEntry.getName()); LOGGER.fine("Extracting file: " + extractedFile.getAbsolutePath()); if(zipEntry.isDirectory()) { if(!extractedFile.exists() && !extractedFile.mkdirs()) { throw new IOException("Can not create folder"); } } else { // Ensure to create the parents directories if(!extractedFile.getParentFile().exists() && !extractedFile.getParentFile().mkdirs()) { throw new IOException("Can not create the parent folder"); } int length; byte[] buffer = new byte[1024]; try(final FileOutputStream extractedFileOutputStream = new FileOutputStream(extractedFile)) { while ((length = zipReader.read(buffer)) > 0) { extractedFileOutputStream.write(buffer, 0, length); } extractedFileOutputStream.flush(); } } } LOGGER.fine("Extraction done"); zipReader.closeEntry(); zipReader.close(); } /** * Compress the given fileToZip into the given destination. This method manages if the fileToZip is a folder or a simple file. * @param fileToZip The content to compress. * @param destination The destination into the content will be compressed. * @throws java.lang.NullPointerException If the fileToZip or the destination is null. * @throws java.io.FileNotFoundException If the fileToZip does not exist. */ public static void zip(File fileToZip, File destination) throws IOException { if(fileToZip == null) throw new NullPointerException("The file to zip can not be null"); if(!fileToZip.exists()) throw new FileNotFoundException("The file to zip does not exist"); if(destination == null) throw new NullPointerException("The destination can not be null"); final ListFilesFileVisitor visitor = new ListFilesFileVisitor(); Files.walkFileTree(fileToZip.toPath(), visitor); final List<File> filesToZip = visitor.getFiles(); FileInputStream fileInput = null; ZipOutputStream zipOutput = new ZipOutputStream(new FileOutputStream(destination)); ZipEntry entry; String entryName; byte[] buffer = new byte[1024]; int length; String prefixToDelete; if(fileToZip.isDirectory()) { prefixToDelete = fileToZip.getAbsolutePath() + File.separator; } else { prefixToDelete = ""; } for(File file : filesToZip) { LOGGER.fine("Compressing file: " + file.getAbsolutePath()); entryName = file.getAbsolutePath().substring(prefixToDelete.length(), file.getAbsolutePath().length()); entryName = entryName.replaceAll("\\\\", "/"); LOGGER.finest("Entry name: " + entryName); if(file.isDirectory()) { entry = new ZipEntry(entryName + "/"); zipOutput.putNextEntry(entry); } else { entry = new ZipEntry(entryName); zipOutput.putNextEntry(entry); try { fileInput = new FileInputStream(file); while((length = fileInput.read(buffer)) > 0) { zipOutput.write(buffer, 0, length); } } finally { fileInput.close(); } } } zipOutput.closeEntry(); zipOutput.flush(); zipOutput.close(); LOGGER.fine("File compressed"); } }