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)
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.
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.
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.
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);
}
}
}
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);
}
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With