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

时间:2015-05-12 06:44:12

标签: java io compression zip fileinputstream

请查看以下代码。

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扩展名。

3 个答案:

答案 0 :(得分: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();
    }
}

答案 1 :(得分:1)

更新自this answer,修复了已添加到其自己目录中的每个文件的问题。也更好地支持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);
                }
            }
        }
    }

}

答案 2 :(得分:1)

这是我的解决方案,它使用新的java.nio包。只需调用zipDir,即可获得该目录的路径。它将在同一位置创建一个zip文件,但称为<directory>.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);
    }
}