Java 使用 Commons IO 将目录压缩为 zipfile
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23318383/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Compress directory into a zipfile with Commons IO
提问by StackUnderflow
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:
我是 Java 编程的初学者,目前正在编写一个必须能够压缩和解压缩.zip
文件的应用程序。我可以使用以下代码使用内置的 Java zip 功能以及 Apache Commons IO 库在 Java 中解压缩 zipfile:
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)
除了我已经在使用的库之外,我将如何从不使用外部库的目录中创建 zipfile?(Java 标准库和 Commons IO)
采纳答案by StackUnderflow
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.
正如我的压缩代码片段中所见,我正在使用它IOUtils.copy()
来处理流数据传输。
回答by legendJSLC
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);
}
}
}
回答by Klesh
Full class ZipUtils
based on answers above.
ZipUtils
基于以上答案的完整课程。
public final class ZipUtils {
private ZipUtils() {
}
// For testing
public static void main(String[] args) throws IOException {
compressFile(new File("./file.test"), new File("test1.zip"));
compressDirectory(new File("./test1"), new File("test2.zip"));
extractArchive(new File("./test2"), new File("test3.zip"));
}
public static void compressDirectory(File sourceDirectory, File zipFile) throws IOException {
Preconditions.checkState(sourceDirectory.exists(), "Source directory is not exists: %s", sourceDirectory);
try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile))) {
compressDirectory(sourceDirectory.getAbsoluteFile(), sourceDirectory, out);
}
}
private static void compressDirectory(File rootDir, File sourceDir, ZipOutputStream out) throws IOException {
for (File file : Preconditions.checkNotNull(sourceDir.listFiles())) {
if (file.isDirectory()) {
compressDirectory(rootDir, new File(sourceDir, file.getName()), out);
} else {
String zipEntryName = getRelativeZipEntryName(rootDir, file);
compressFile(out, file, zipEntryName);
}
}
}
private static String getRelativeZipEntryName(File rootDir, File file) {
return StringUtils.removeStart(file.getAbsolutePath(), rootDir.getAbsolutePath());
}
public static void compressFile(File file, File zipFile) throws IOException {
try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile))) {
compressFile(out, file, file.getName());
}
}
private static void compressFile(ZipOutputStream out, File file, String zipEntityName) throws IOException {
ZipEntry entry = new ZipEntry(zipEntityName);
out.putNextEntry(entry);
try (FileInputStream in = new FileInputStream(file)) {
IOUtils.copy(in, out);
}
}
public static void extractArchive(File targetDirectory, File zipFile) throws IOException {
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
extractStream(targetDirectory, zis);
}
}
private static void extractStream(File targetDirectory, ZipInputStream zis) throws IOException {
ZipEntry zipEntry = zis.getNextEntry();
while (zipEntry != null) {
extractEntry(targetDirectory, zis, zipEntry);
zipEntry = zis.getNextEntry();
}
zis.closeEntry();
}
private static void extractEntry(File targetDirectory, ZipInputStream zis, ZipEntry zipEntry) throws IOException {
File newFile = newFile(targetDirectory, zipEntry);
if (zipEntry.isDirectory()) {
FileUtils.forceMkdir(newFile);
} else {
FileUtils.forceMkdirParent(newFile);
try (FileOutputStream fos = new FileOutputStream(newFile)) {
IOUtils.copy(zis, fos);
}
}
}
private static File newFile(File targetDirectory, ZipEntry zipEntry) throws IOException {
File targetFile = new File(targetDirectory, zipEntry.getName());
String targetDirPath = targetDirectory.getCanonicalPath();
String targetFilePath = targetFile.getCanonicalPath();
if (!targetFilePath.startsWith(targetDirPath + File.separator)) {
throw new IOException("Entry is outside of the target dir: " + zipEntry.getName());
}
return targetFile;
}
}
回答by Aldis
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.
看起来答案有点过时了。暂时将其刷新为最新的 Java。同样在 ZIP 文件中,文件名将相对于给定文件夹进行压缩。在原始答案中,它们是绝对的,具有完整的路径。
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);
}
}
}
}
}