Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compress directory into a zipfile with Commons IO

I am a beginner at programming with Java and am currently writing an application which must be able to compress and decompress .zip files. I can use the following code to decompress a zipfile in Java using the built-in Java zip functionality as well as the Apache Commons IO library:

public static void decompressZipfile(String file, String outputDir) throws IOException {
    if (!new File(outputDir).exists()) {
        new File(outputDir).mkdirs();
    }
    ZipFile zipFile = new ZipFile(file);
    Enumeration<? extends ZipEntry> entries = zipFile.entries();
    while (entries.hasMoreElements()) {
        ZipEntry entry = entries.nextElement();
        File entryDestination = new File(outputDir, entry.getName());
        if (entry.isDirectory()) {
            entryDestination.mkdirs();
        } else {
            InputStream in = zipFile.getInputStream(entry);
            OutputStream out = new FileOutputStream(entryDestination);
            IOUtils.copy(in, out);
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(out);
        }
    }
}

How would I go about creating a zipfile from a directory using no external libraries other than what I am already using? (Java standard libraries and Commons IO)

like image 251
StackUnderflow Avatar asked Apr 27 '14 01:04

StackUnderflow


People also ask

What is the use of Commons compress?

The Apache Commons Compress library defines an API for working with ar, cpio, Unix dump, tar, zip, gzip, XZ, Pack200, bzip2, 7z, arj, lzma, snappy, DEFLATE, lz4, Brotli, Zstandard, DEFLATE64 and Z files.

How can I zip a file in Java?

Steps to Compress a File in JavaOpen a ZipOutputStream that wraps an OutputStream like FileOutputStream. The ZipOutputStream class implements an output stream filter for writing in the ZIP file format. Put a ZipEntry object by calling the putNextEntry(ZipEntry) method on the ZipOutputStream.


3 Answers

The following method(s) seem to successfully compress a directory recursively:

public static void compressZipfile(String sourceDir, String outputFile) throws IOException, FileNotFoundException {
    ZipOutputStream zipFile = new ZipOutputStream(new FileOutputStream(outputFile));
    compressDirectoryToZipfile(sourceDir, sourceDir, zipFile);
    IOUtils.closeQuietly(zipFile);
}

private static void compressDirectoryToZipfile(String rootDir, String sourceDir, ZipOutputStream out) throws IOException, FileNotFoundException {
    for (File file : new File(sourceDir).listFiles()) {
        if (file.isDirectory()) {
            compressDirectoryToZipfile(rootDir, sourceDir + File.separator + file.getName(), out);
        } else {
            ZipEntry entry = new ZipEntry(sourceDir.replace(rootDir, "") + file.getName());
            out.putNextEntry(entry);

            FileInputStream in = new FileInputStream(sourceDir + file.getName());
            IOUtils.copy(in, out);
            IOUtils.closeQuietly(in);
        }
    }
}

As seen in my compression code snippet, I'm using IOUtils.copy() to handle stream data transfer.

like image 81
StackUnderflow Avatar answered Sep 25 '22 20:09

StackUnderflow


I fix above error and it works perfect.

    public static void compressZipfile(String sourceDir, String outputFile) throws IOException, FileNotFoundException {
    ZipOutputStream zipFile = new ZipOutputStream(new FileOutputStream(outputFile));
    Path srcPath = Paths.get(sourceDir);
    compressDirectoryToZipfile(srcPath.getParent().toString(), srcPath.getFileName().toString(), zipFile);
    IOUtils.closeQuietly(zipFile);
}

private static void compressDirectoryToZipfile(String rootDir, String sourceDir, ZipOutputStream out) throws IOException, FileNotFoundException {
    String dir = Paths.get(rootDir, sourceDir).toString();
    for (File file : new File(dir).listFiles()) {
        if (file.isDirectory()) {
            compressDirectoryToZipfile(rootDir, Paths.get(sourceDir,file.getName()).toString(), out);
        } else {
            ZipEntry entry = new ZipEntry(Paths.get(sourceDir,file.getName()).toString());
            out.putNextEntry(entry);

            FileInputStream in = new FileInputStream(Paths.get(rootDir, sourceDir, file.getName()).toString());
            IOUtils.copy(in, out);
            IOUtils.closeQuietly(in);
        }
    }
}
like image 37
legendJSLC Avatar answered Sep 22 '22 20:09

legendJSLC


Looks like the answer is a bit outdated. Refreshed it for latest Java for now. Also in ZIP file file names will be relative to given folder for compression. In original answer they were absolute with full paths.

import org.apache.commons.io.IOUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class Zipper {

    public static void compressFolder(String sourceDir, String outputFile) throws IOException {
        try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(outputFile))) {
            compressDirectoryToZipFile((new File(sourceDir)).toURI(), new File(sourceDir), zipOutputStream);
        }
    }

    private static void compressDirectoryToZipFile(URI basePath, File dir, ZipOutputStream out) throws IOException {
        List<File> fileList = Files.list(Paths.get(dir.getAbsolutePath()))
                .map(Path::toFile)
                .collect(Collectors.toList());
        for (File file : fileList) {
            if (file.isDirectory()) {
                compressDirectoryToZipFile(basePath, file, out);
            } else {
                out.putNextEntry(new ZipEntry(basePath.relativize(file.toURI()).getPath()));
                try (FileInputStream in = new FileInputStream(file)) {
                    IOUtils.copy(in, out);
                }
            }
        }
    }

}
like image 32
Aldis Avatar answered Sep 25 '22 20:09

Aldis