如何在Java中压缩目录内容

6
我正在使用以下Java代码,但是当它压缩文件时,它会创建一个目录并将所有内容压缩在该目录中。 例如,如果我有一个名为“Directory”的文件夹,并且想将其内容压缩到一个压缩文件中,在压缩文件中,它会创建一个名为testZip的文件夹,并在其中包含文件。 我需要所有文件都在压缩文件中,而不是在父目录中。 请帮忙解决或提供其他方法。
package folderZip;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipFolder {
    public ZipFolder() {  
    }  


    public static void main(String[] args) throws Exception {
        ZipFolder obj = new ZipFolder();
        obj.zipFolder("C:\\Drive\\temp\\testZip","C:\\Drive\\temp\\FolderZiper.zip");       
    }


     public void zipFolder(String srcFolder,
                                 String destZipFile) throws Exception {
        ZipOutputStream zip = null;
        FileOutputStream fileWriter = null;

        fileWriter = new FileOutputStream(destZipFile);
        zip = new ZipOutputStream(fileWriter);

        addFolderToZip("", srcFolder, zip);

        zip.flush();
        zip.close();

    }

    private void addFileToZip(String path, String srcFile,
                                     ZipOutputStream zip) throws Exception {

        File folder = new File(srcFile);
        if (folder.isDirectory()) {
            addFolderToZip(path, srcFile, zip);
        } else {
            byte[] buf = new byte[1024];
            int len;
            FileInputStream in = new FileInputStream(srcFile);
            zip.putNextEntry(new ZipEntry(path + "/" + folder.getName()));
            while ((len = in.read(buf)) > 0) {
                zip.write(buf, 0, len);
            }
        }
    }

    private void addFolderToZip(String path, String srcFolder,
                                       ZipOutputStream zip) throws Exception {
        File folder = new File(srcFolder);

        for (String fileName : folder.list()) {
            if (path.equals("")) {
                addFileToZip(folder.getName(), srcFolder + "/" + fileName,
                             zip);
            } else {
                addFileToZip(path + "/" + folder.getName(),
                             srcFolder + "/" + fileName, zip);
            }
        }
    }
}

基本上,如果我理解你的问题,你需要从所需的zip条目名称中剥离“source”文件夹名称。类似于这个例子这个例子以及这个例子 - MadProgrammer
尝试这个:当前文件夹是“testing”,创建一个名为“testfolder”的子文件夹。 testfolder有多个文件,其中之一是“user-guide.pdf”。程序应该能够创建一个ZIP文件夹,只有一个条目user-guide.pdf - 输出zip文件“MyZip”将只有一个文件user-guide.pdf。输出zip文件将在您选择的文件夹中创建 - testing或testfolder。如果您能够做到这一点,您可以将相同的逻辑应用于您正在尝试的应用程序。此外,可以使用Files.walkFileTreeFileVisitor API遍历文件树并压缩内容。 - prasad_
3个回答

8
所以,如果我理解正确,您想要的是,在Zip文件中不出现目标文件夹,而是所有文件都应该从 "/" 开始。

例如,如果您有以下文件:

FolderToZip/
    TestFile1.txt
    TestFile2.txt
    TestFile3.txt
    SomeSubFolder/
        TestFile4.txt
        TestFile5.txt
        TestFile6.txt

Zip文件的内容应包含:
TestFile1.txt
TestFile2.txt
TestFile3.txt
SomeSubFolder/
    TestFile4.txt
    TestFile5.txt
    TestFile6.txt

为了实现这个,你需要保留对“开始”文件夹的引用,并去掉要添加的文件路径,以创建 ZipEntry
为了简化操作,我将你的代码更改为支持 File 而不是 String,这样整个过程就不会那么混乱了。
但是魔法就在这里...
FileInputStream in = new FileInputStream(srcFile);
String name = srcFile.getPath();
name = name.replace(rootPath.getPath(), "");
System.out.println("Zip " + srcFile + "\n to " + name);
zip.putNextEntry(new ZipEntry(name));

rootPath是初始文件夹(在您的示例中为C:\\Drive\\temp\\testZip"),srcFile是要添加的文件。

可运行示例...

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


public class ZipFolder {

    public ZipFolder() {
    }

    public static void main(String[] args) throws Exception {
        ZipFolder obj = new ZipFolder();
        obj.zipFolder(new File("/Users/shanewhitehead/exports"),
                new File("FolderZiper.zip"));
    }

    public void zipFolder(File srcFolder, File destZipFile) throws Exception {
        try (FileOutputStream fileWriter = new FileOutputStream(destZipFile);
                ZipOutputStream zip = new ZipOutputStream(fileWriter)) {

            addFolderToZip(srcFolder, srcFolder, zip);
        }
    }

    private void addFileToZip(File rootPath, File srcFile, ZipOutputStream zip) throws Exception {

        if (srcFile.isDirectory()) {
            addFolderToZip(rootPath, srcFile, zip);
        } else {
            byte[] buf = new byte[1024];
            int len;
            try (FileInputStream in = new FileInputStream(srcFile)) {
                String name = srcFile.getPath();
                name = name.replace(rootPath.getPath(), "");
                System.out.println("Zip " + srcFile + "\n to " + name);
                zip.putNextEntry(new ZipEntry(name));
                while ((len = in.read(buf)) > 0) {
                    zip.write(buf, 0, len);
                }
            }
        }
    }

    private void addFolderToZip(File rootPath, File srcFolder, ZipOutputStream zip) throws Exception {
        for (File fileName : srcFolder.listFiles()) {
            addFileToZip(rootPath, fileName, zip);
        }
    }
}

我还清理了您的资源管理,使用try-with-resources


非常感谢,你救了我的一天 :) 我只做了一个小修改,在 Windows 中 zip 文件中添加了一个 '',所以我添加了:name = name.replace(rootPath.getPath(), ""); name = name.substring(1); 来删除第一个 ''。不确定在 Linux 中是否已经正常工作,将进行测试。 - Vivek Vishal

0

使用这个库怎么样 Zeroturnaround Zip library
然后你只需一行命令就可以压缩你的文件夹:

ZipUtil.pack(new File("D:\\sourceFolder\\"), new File("D:\\generatedZipFile.zip"));

0
你可以这样调用。
zipFoldersAndFiles(Paths.get(sourcesPath), Paths.get(exportLocationPath));

声明方法。

private void zipFoldersAndFiles(Path sourcesFolderPath, Path zipPath){

    new Thread(() -> {

        try {
            ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zipPath.toFile()));

            Files.walkFileTree(sourcesFolderPath, new SimpleFileVisitor<Path>() {

                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {

                    zipOutputStream.putNextEntry(new ZipEntry(sourcesFolderPath.relativize(file).toString()));
                    zipOutputStream.setLevel(ZipOutputStream.STORED);
                    Files.copy(file, zipOutputStream);
                    zipOutputStream.closeEntry();
                    return FileVisitResult.CONTINUE;
                }
            });

            zipOutputStream.close();
        }
        catch (Exception e){
            System.out.println("error");
        }
    }).start();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接