使用Commons IO将目录压缩到zip文件中



我是Java编程的初学者,目前正在编写一个必须能够压缩和解压缩.zip文件的应用程序。我可以使用以下代码使用内置的Java zip功能以及Apache Commons IO库在Java中解压缩zip文件:

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);
        }
    }
}

我该如何从一个目录中创建一个zip文件,除了我已经在使用的库之外,不使用任何外部库?(Java标准库和Commons IO)

以下方法似乎可以成功地递归压缩目录:

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);
        }
    }
}

正如在我的压缩代码片段中看到的,我使用IOUtils.copy()来处理流数据传输。

我修复了上面的错误,它运行得很好。

    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);
        }
    }
}

看起来答案有点过时了。目前已更新为最新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);
                }
            }
        }
    }
}

基于以上答案的全班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;
    }
}

相关内容

  • 没有找到相关文章

最新更新