如何在Java中压缩文件和文件夹?

3
请看下面的代码。
public void startCompress(String path,String fileName,String outputLocation,int compressType,int filSize) throws Exception
    {        
        System.out.println("Input Location: "+path);
        System.out.println("Output Location: "+outputLocation);   

            System.out.println(compressType);
            byte[] bs=new byte[filSize];
            System.out.println(filSize);

            FileOutputStream fos=new FileOutputStream(outputLocation+"/test.zip");

            System.out.println(fos.toString());
            ZipOutputStream zos=new ZipOutputStream(fos);

            ZipEntry ze = new ZipEntry(fileName);

            zos.putNextEntry(ze);

            FileInputStream inputStream=new FileInputStream(path);

            int len;
            while((len=inputStream.read(bs))>0){
                zos.write(bs, 0, len);                
            }
            inputStream.close();
            zos.closeEntry();
            zos.close();

    }

在上面的代码中,我们使用java.util.zip包来压缩文件。但是我们有一个问题,如果我们选择多个文件,则只会压缩其中一个文件。如果我们选择一个文件夹,那么压缩根本不起作用。
如何修复这个问题,以便压缩单个文件、多个文件、文件夹、多个文件夹甚至是嵌套文件夹?Java zip包支持.zip、.tar、.tarGz和tarZ格式,因此解决方案不应仅限于.zip扩展名。

然后将文件列表传递给它...类似于这样的链接或者链接 - MadProgrammer
1
http://www.mkyong.com/java/how-to-compress-files-in-zip-format/ 以及 https://dev59.com/xWQo5IYBdhLWcg3wiv0i - Sercan Ozdemir
@SercanOzdemir:他的例子不同,我们还需要确定所选内容是文件还是文件夹。 - PeakGen
@MadProgrammer:很高兴你在这里。你能帮我提供一些代码示例吗? - PeakGen
@JustCause 请查看这两个链接的示例(已更新评论)。 - MadProgrammer
显示剩余11条评论
3个回答

2

Java的zip库不能像“压缩此文件夹”这样简单地压缩文件夹。

您需要自行测试输入是文件还是文件夹。如果是文件-将其添加到zip中。如果是文件夹-迭代该文件夹并将每个文件添加到zip中。对于子文件夹也是如此。要将多个文件添加到Zip,您需要为每个文件创建ZipEntry。

您可以尝试这段代码,它对我有效:

public static void zip(File directory, File zipfile) throws IOException {
    URI base = directory.toURI();
    Deque<File> queue = new LinkedList<File>();
    queue.push(directory);
    OutputStream out = new FileOutputStream(zipfile);
    Closeable res = out;
    try {
        ZipOutputStream zout = new ZipOutputStream(out);
        res = zout;
        while (!queue.isEmpty()) {
            directory = queue.pop();
            for (File kid : directory.listFiles()) {
                String name = base.relativize(kid.toURI()).getPath();
                if (kid.isDirectory()) {
                    queue.push(kid);
                    name = name.endsWith("/") ? name : name + "/";
                    zout.putNextEntry(new ZipEntry(name));
                } else {
                    zout.putNextEntry(new ZipEntry(name));
                    copy(kid, zout);
                    zout.closeEntry();
                }
            }
        }
    } finally {
        res.close();
    }
}

2

这里是我使用新的java.nio包提供的解决方案。只需调用zipDir并给出目录的路径即可。它将在同一位置创建一个名为<directory>.zip的zip文件。

private static Path buildPath(final Path root, final Path child) {
    if (root == null) {
        return child;
    } else {
        return Paths.get(root.toString(), child.toString());
    }
}

private static void addZipDir(final ZipOutputStream out, final Path root, final Path dir) throws IOException {
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
        for (Path child : stream) {
            Path entry = buildPath(root, child.getFileName());
            if (Files.isDirectory(child)) {
                addZipDir(out, entry, child);
            } else {
                out.putNextEntry(new ZipEntry(entry.toString()));
                Files.copy(child, out);
                out.closeEntry();
            }
        }
    }
}

public static void zipDir(final Path path) throws IOException {
    if (!Files.isDirectory(path)) {
        throw new IllegalArgumentException("Path must be a directory.");
    }

    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path.toString() + ".zip"));

    try (ZipOutputStream out = new ZipOutputStream(bos)) {
        addZipDir(out, path.getFileName(), path);
    }
}

1

更新自此答案,修复了每个文件被添加到自己的目录中的问题。同时更好地支持Windows资源管理器。

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

public class Test {

    public static void main(String agrs[]) {
        ZipUtils appZip = new ZipUtils();
        appZip.zipIt(new File(source directory), new File(dest zip));
    }

    public static class ZipUtils {

        private final List<File> fileList;

        private List<String> paths;

        public ZipUtils() {
            fileList = new ArrayList<>();
            paths = new ArrayList<>(25);
        }

        public void zipIt(File sourceFile, File zipFile) {
            if (sourceFile.isDirectory()) {
                byte[] buffer = new byte[1024];
                FileOutputStream fos = null;
                ZipOutputStream zos = null;

                try {

                    // This ensures that the zipped files are placed
                    // into a folder, within the zip file
                    // which is the same as the one been zipped
                    String sourcePath = sourceFile.getParentFile().getPath();
                    generateFileList(sourceFile);

                    fos = new FileOutputStream(zipFile);
                    zos = new ZipOutputStream(fos);

                    System.out.println("Output to Zip : " + zipFile);
                    FileInputStream in = null;

                    for (File file : this.fileList) {
                        String path = file.getParent().trim();
                        path = path.substring(sourcePath.length());

                        if (path.startsWith(File.separator)) {
                            path = path.substring(1);
                        }

                        if (path.length() > 0) {
                            if (!paths.contains(path)) {
                                paths.add(path);
                                ZipEntry ze = new ZipEntry(path + "/");
                                zos.putNextEntry(ze);
                                zos.closeEntry();
                            }
                            path += "/";
                        }

                        String entryName = path + file.getName();
                        System.out.println("File Added : " + entryName);
                        ZipEntry ze = new ZipEntry(entryName);

                        zos.putNextEntry(ze);
                        try {
                            in = new FileInputStream(file);
                            int len;
                            while ((len = in.read(buffer)) > 0) {
                                zos.write(buffer, 0, len);
                            }
                        } finally {
                            in.close();
                        }
                    }

                    zos.closeEntry();
                    System.out.println("Folder successfully compressed");

                } catch (IOException ex) {
                    ex.printStackTrace();
                } finally {
                    try {
                        zos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        protected void generateFileList(File node) {

// add file only
            if (node.isFile()) {
                fileList.add(node);

            }

            if (node.isDirectory()) {
                File[] subNote = node.listFiles();
                for (File filename : subNote) {
                    generateFileList(filename);
                }
            }
        }
    }

}

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