如何使用java压缩文件夹本身

muk*_*und 62 java directory zip

假设我有以下目录结构.

D:\reports\january\
Run Code Online (Sandbox Code Playgroud)

一月份内部有两个excel文件说A.xls和B.xls.有许多地方已经写过如何使用zip文件java.util.zip.但是,我要压缩报告文件夹中的文件夹一月本身这样既月份january.zip将出席内部报告.(这意味着当我解压缩january.zip文件时,我应该获得january文件夹).

任何人都可以请我提供使用的代码java.util.zip.请告诉我是否可以通过使用其他库来更轻松地完成此操作.

非常感谢...

Pet*_*iuk 88

你有没有尝试过Zeroturnaround Zip库?它真的很整洁!拉链文件夹只是一个班轮:

ZipUtil.pack(new File("D:\\reports\\january\\"), new File("D:\\reports\\january.zip"));
Run Code Online (Sandbox Code Playgroud)

(感谢OlegŠelajev的例子)


Nik*_*rov 73

这是Java 8+示例:

public static void pack(String sourceDirPath, String zipFilePath) throws IOException {
    Path p = Files.createFile(Paths.get(zipFilePath));
    try (ZipOutputStream zs = new ZipOutputStream(Files.newOutputStream(p))) {
        Path pp = Paths.get(sourceDirPath);
        Files.walk(pp)
          .filter(path -> !Files.isDirectory(path))
          .forEach(path -> {
              ZipEntry zipEntry = new ZipEntry(pp.relativize(path).toString());
              try {
                  zs.putNextEntry(zipEntry);
                  Files.copy(path, zs);
                  zs.closeEntry();
            } catch (IOException e) {
                System.err.println(e);
            }
          });
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 获取ZipEntry的相对路径可以简化为`new ZipEntry(pp.relativize(path).toString())` (3认同)
  • 抛出新的RuntimeException(e)优于System.err.println(e) (3认同)
  • 小改进:将 ZipOutpuStream 放入 try (...) { }; 对于 sp,我添加了 .replace("\\", "/"); 将 sp + "/" + 路径... 替换为 sp + 路径... (2认同)
  • 如果文件大小很大,那么Files.readAllBytes()会不会导致内存膨胀? (2认同)

kar*_*ark 55

它可以通过包解决,java.util.Zip无需任何额外的Jar文件

就在下面的代码,并复制run itIDE

//Import all needed packages
package general;
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 ZipUtils {

    private List <String> fileList;
    private static final String OUTPUT_ZIP_FILE = "Folder.zip";
    private static final String SOURCE_FOLDER = "D:\\Reports"; // SourceFolder path

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

    public static void main(String[] args) {
        ZipUtils appZip = new ZipUtils();
        appZip.generateFileList(new File(SOURCE_FOLDER));
        appZip.zipIt(OUTPUT_ZIP_FILE);
    }

    public void zipIt(String zipFile) {
        byte[] buffer = new byte[1024];
        String source = new File(SOURCE_FOLDER).getName();
        FileOutputStream fos = null;
        ZipOutputStream zos = null;
        try {
            fos = new FileOutputStream(zipFile);
            zos = new ZipOutputStream(fos);

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

            for (String file: this.fileList) {
                System.out.println("File Added : " + file);
                ZipEntry ze = new ZipEntry(source + File.separator + file);
                zos.putNextEntry(ze);
                try {
                    in = new FileInputStream(SOURCE_FOLDER + File.separator + 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();
            }
        }
    }

    public void generateFileList(File node) {
        // add file only
        if (node.isFile()) {
            fileList.add(generateZipEntry(node.toString()));
        }

        if (node.isDirectory()) {
            String[] subNote = node.list();
            for (String filename: subNote) {
                generateFileList(new File(node, filename));
            }
        }
    }

    private String generateZipEntry(String file) {
        return file.substring(SOURCE_FOLDER.length() + 1, file.length());
    }
}
Run Code Online (Sandbox Code Playgroud)

请参阅mkyong ..我更改了当前问题要求的代码


jjs*_*jst 33

这是一个非常简洁的Java 7+解决方案,完全依赖于vanilla JDK类,不需要第三方库:

public static void pack(final Path folder, final Path zipFilePath) throws IOException {
    try (
            FileOutputStream fos = new FileOutputStream(zipFilePath.toFile());
            ZipOutputStream zos = new ZipOutputStream(fos)
    ) {
        Files.walkFileTree(folder, new SimpleFileVisitor<Path>() {
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                zos.putNextEntry(new ZipEntry(folder.relativize(file).toString()));
                Files.copy(file, zos);
                zos.closeEntry();
                return FileVisitResult.CONTINUE;
            }

            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                zos.putNextEntry(new ZipEntry(folder.relativize(dir).toString() + "/"));
                zos.closeEntry();
                return FileVisitResult.CONTINUE;
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

它复制所有文件folder,包括空目录,并在其中创建一个zip存档zipFilePath.

  • 这对我来说在Windows上没有问题,只是为我跳过"preVisitDirectory"的覆盖(因为它是相对的,所有子文件夹都是生成的).据我所知,只有一个缺点:空文件夹被跳过 (3认同)
  • 你可以说得更详细点吗?你遇到了什么样的问题? (2认同)

Ton*_*him 11

Java 7 +,commons.io

public final class ZipUtils {

    public static void zipFolder(final File folder, final File zipFile) throws IOException {
        zipFolder(folder, new FileOutputStream(zipFile));
    }

    public static void zipFolder(final File folder, final OutputStream outputStream) throws IOException {
        try (ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream)) {
            processFolder(folder, zipOutputStream, folder.getPath().length() + 1);
        }
    }

    private static void processFolder(final File folder, final ZipOutputStream zipOutputStream, final int prefixLength)
            throws IOException {
        for (final File file : folder.listFiles()) {
            if (file.isFile()) {
                final ZipEntry zipEntry = new ZipEntry(file.getPath().substring(prefixLength));
                zipOutputStream.putNextEntry(zipEntry);
                try (FileInputStream inputStream = new FileInputStream(file)) {
                    IOUtils.copy(inputStream, zipOutputStream);
                }
                zipOutputStream.closeEntry();
            } else if (file.isDirectory()) {
                processFolder(file, zipOutputStream, prefixLength);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 如果你想删除对 commons.io 的依赖,`IOUtils.copy` 方法几乎就是:`byte [] buffer = new byte[1024 * 4]; 读取的整数=0;while ((read = input.read(buffer)) != -1) { 输出.write(buffer, 0, read); }` (2认同)

hal*_*lex 7

我通常使用我曾经为此任务编写的辅助类:

import java.util.zip.*;
import java.io.*;

public class ZipExample {
    public static void main(String[] args){
        ZipHelper zippy = new ZipHelper();
        try {
            zippy.zipDir("folderName","test.zip");
        } catch(IOException e2) {
            System.err.println(e2);
        }
    }
}

class ZipHelper  
{
    public void zipDir(String dirName, String nameZipFile) throws IOException {
        ZipOutputStream zip = null;
        FileOutputStream fW = null;
        fW = new FileOutputStream(nameZipFile);
        zip = new ZipOutputStream(fW);
        addFolderToZip("", dirName, zip);
        zip.close();
        fW.close();
    }

    private void addFolderToZip(String path, String srcFolder, ZipOutputStream zip) throws IOException {
        File folder = new File(srcFolder);
        if (folder.list().length == 0) {
            addFileToZip(path , srcFolder, zip, true);
        }
        else {
            for (String fileName : folder.list()) {
                if (path.equals("")) {
                    addFileToZip(folder.getName(), srcFolder + "/" + fileName, zip, false);
                } 
                else {
                     addFileToZip(path + "/" + folder.getName(), srcFolder + "/" + fileName, zip, false);
                }
            }
        }
    }

    private void addFileToZip(String path, String srcFile, ZipOutputStream zip, boolean flag) throws IOException {
        File folder = new File(srcFile);
        if (flag) {
            zip.putNextEntry(new ZipEntry(path + "/" +folder.getName() + "/"));
        }
        else {
            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);
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 完成后,应关闭FileInputStream的输入流. (3认同)

Abd*_*auf 5

增强的Java 8+示例(从Nikita Koksharov的答案中派生出来

public static void pack(String sourceDirPath, String zipFilePath) throws IOException {
    Path p = Files.createFile(Paths.get(zipFilePath));
    Path pp = Paths.get(sourceDirPath);
    try (ZipOutputStream zs = new ZipOutputStream(Files.newOutputStream(p));
        Stream<Path> paths = Files.walk(pp)) {
        paths
          .filter(path -> !Files.isDirectory(path))
          .forEach(path -> {
              ZipEntry zipEntry = new ZipEntry(pp.relativize(path).toString());
              try {
                  zs.putNextEntry(zipEntry);
                  Files.copy(path, zs);
                  zs.closeEntry();
            } catch (IOException e) {
                System.err.println(e);
            }
          });
    }
}
Run Code Online (Sandbox Code Playgroud)

Files.walk已被包装在try with resources块中,以便可以关闭流。这解决了由标识的阻止程序问题SonarQube。感谢@Matt Harrison指出这一点。


sva*_*rog 5

使用zip4j你可以简单地做到这一点

ZipFile zipfile = new ZipFile(new File("D:\\reports\\january\\filename.zip"));
zipfile.addFolder(new File("D:\\reports\\january\\"));
Run Code Online (Sandbox Code Playgroud)

它将存档您的文件夹及其中的所有内容。

使用以下.extractAll方法将其全部弄清楚:

zipfile.extractAll("D:\\destination_directory");
Run Code Online (Sandbox Code Playgroud)